feat(color): LVGLify and enhance Logical Switches page (#3019)
* Update logical switch layout: - Use LVGL flex / grid layout - Same height for all buttons - Display logical switch name inside button so entire row acts as button - Consistent press handler for buttons (always show popup menu) - Group buttons for empty switch in lines to utilise space - Remember selected button and reselect after edit. * Fix incorrect switch being selected when changing tabs. * Fix selection of focussed button when using 'Clear', and switching tabs. * Reorganise logical switch edit code. * Change button style to match input/mixes/outputs pages. * Single line overview on landscape LCD layout. Convert to using grid and lgvl objects for overview buttons. * Remove redundant flag. * Remove logic that tries to center scroll around selected button (not working). * Remove empty buttons and add a single '+' button at the bottom to match inputs and mixes. * Remove unused code. * Correct string usage. * Add long press handler for quick access to the '+' button functions. * Display logical switch operation and parameters as an expression. Add 's' suffix to time values. * Adjust spacing. * Set V2 number edit control to automatically resize and fit content to prevent clipping of large values. * Revert to fixed column layout. * Adjust grid spacing. * Convert the logical switch view in the channel monitor to LVGL flex. * chore: Formatting Co-authored-by: Phil Mitchell <phil.a.mitchell@gmail.com> Co-authored-by: Peter Feerick <peter.feerick@gmail.com>
This commit is contained in:
co-authored by
Phil Mitchell
Peter Feerick
parent
7e026e2b49
commit
d77389d30b
@@ -23,152 +23,110 @@
|
||||
#include "opentx.h"
|
||||
#include "libopenui.h"
|
||||
#include "switches.h"
|
||||
#include "lvgl_widgets/input_mix_line.h"
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
void putsEdgeDelayParam(BitmapBuffer * dc, coord_t x, coord_t y, LogicalSwitchData * ls, LcdFlags flags = 0)
|
||||
static const lv_coord_t col_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(3),
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t 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 LogicalSwitchEditPage : public Page
|
||||
{
|
||||
coord_t lcdNextPos = 0;
|
||||
lcdNextPos = dc->drawText(x, y, "[", flags);
|
||||
lcdNextPos = dc->drawNumber(lcdNextPos+2, y, lswTimerValue(ls->v2), LEFT | PREC1 | flags);
|
||||
lcdNextPos = dc->drawText(lcdNextPos, y, ":", flags);
|
||||
if (ls->v3 < 0)
|
||||
lcdNextPos = dc->drawText(lcdNextPos+3, y, "<<", flags);
|
||||
else if (ls->v3 == 0)
|
||||
lcdNextPos = dc->drawText(lcdNextPos+3, y, "--", flags);
|
||||
else
|
||||
lcdNextPos = dc->drawNumber(lcdNextPos+3, y, lswTimerValue(ls->v2+ls->v3), LEFT | PREC1 | flags);
|
||||
dc->drawText(lcdNextPos, y, "]", flags);
|
||||
}
|
||||
public:
|
||||
explicit LogicalSwitchEditPage(uint8_t index) :
|
||||
Page(ICON_MODEL_LOGICAL_SWITCHES), index(index)
|
||||
{
|
||||
buildHeader(&header);
|
||||
buildBody(&body);
|
||||
}
|
||||
|
||||
class LogicalSwitchEditPage: public Page
|
||||
{
|
||||
public:
|
||||
explicit LogicalSwitchEditPage(uint8_t index):
|
||||
Page(ICON_MODEL_LOGICAL_SWITCHES),
|
||||
index(index)
|
||||
{
|
||||
buildHeader(&header);
|
||||
buildBody(&body);
|
||||
}
|
||||
protected:
|
||||
uint8_t index;
|
||||
bool active = false;
|
||||
FormGroup* logicalSwitchOneWindow = nullptr;
|
||||
StaticText* headerSwitchName = nullptr;
|
||||
NumberEdit* v2Edit = nullptr;
|
||||
|
||||
protected:
|
||||
uint8_t index;
|
||||
bool active = false;
|
||||
FormGroup * logicalSwitchOneWindow = nullptr;
|
||||
StaticText * headerSwitchName = nullptr;
|
||||
NumberEdit * v2Edit = nullptr;
|
||||
bool isActive() const
|
||||
{
|
||||
return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + index);
|
||||
}
|
||||
|
||||
bool isActive() const
|
||||
{
|
||||
return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + index);
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
Page::checkEvents();
|
||||
if (active != isActive()) {
|
||||
if(isActive()) {
|
||||
lv_obj_add_state(headerSwitchName->getLvObj(), LV_STATE_USER_1);
|
||||
} else {
|
||||
lv_obj_clear_state(headerSwitchName->getLvObj(), LV_STATE_USER_1);
|
||||
}
|
||||
active = isActive();
|
||||
invalidate();
|
||||
void checkEvents() override
|
||||
{
|
||||
Page::checkEvents();
|
||||
if (active != isActive()) {
|
||||
if (isActive()) {
|
||||
lv_obj_add_state(headerSwitchName->getLvObj(), LV_STATE_USER_1);
|
||||
} else {
|
||||
lv_obj_clear_state(headerSwitchName->getLvObj(), LV_STATE_USER_1);
|
||||
}
|
||||
active = isActive();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
header.setTitle(STR_MENULOGICALSWITCHES);
|
||||
headerSwitchName = new StaticText(
|
||||
window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
|
||||
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
|
||||
getSwitchPositionName(SWSRC_SW1 + index), 0, COLOR_THEME_PRIMARY2);
|
||||
void buildHeader(Window* window)
|
||||
{
|
||||
header.setTitle(STR_MENULOGICALSWITCHES);
|
||||
headerSwitchName = new StaticText(
|
||||
window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
|
||||
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
|
||||
getSwitchPositionName(SWSRC_SW1 + index), 0, COLOR_THEME_PRIMARY2);
|
||||
|
||||
lv_obj_set_style_text_color(headerSwitchName->getLvObj(), makeLvColor(COLOR_THEME_ACTIVE), LV_STATE_USER_1);
|
||||
lv_obj_set_style_text_font(headerSwitchName->getLvObj(), getFont(FONT(BOLD)), LV_STATE_USER_1);
|
||||
}
|
||||
lv_obj_set_style_text_color(headerSwitchName->getLvObj(),
|
||||
makeLvColor(COLOR_THEME_ACTIVE),
|
||||
LV_STATE_USER_1);
|
||||
lv_obj_set_style_text_font(headerSwitchName->getLvObj(),
|
||||
getFont(FONT(BOLD)), LV_STATE_USER_1);
|
||||
}
|
||||
|
||||
void updateLogicalSwitchOneWindow()
|
||||
{
|
||||
FormGridLayout grid;
|
||||
logicalSwitchOneWindow->clear();
|
||||
void updateLogicalSwitchOneWindow()
|
||||
{
|
||||
SwitchChoice* choice;
|
||||
NumberEdit* timer;
|
||||
|
||||
LogicalSwitchData * cs = lswAddress(index);
|
||||
uint8_t cstate = lswFamily(cs->func);
|
||||
logicalSwitchOneWindow->clear();
|
||||
logicalSwitchOneWindow->setFlexLayout();
|
||||
FlexGridLayout grid(col_dsc, row_dsc, 2);
|
||||
FlexGridLayout grid2(col_dsc2, row_dsc, 2);
|
||||
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V1, 0, COLOR_THEME_PRIMARY1);
|
||||
auto choice = new SwitchChoice(logicalSwitchOneWindow, grid.getFieldSlot(), SWSRC_FIRST_IN_LOGICAL_SWITCHES, SWSRC_LAST_IN_LOGICAL_SWITCHES, GET_SET_DEFAULT(cs->v1));
|
||||
LogicalSwitchData* cs = lswAddress(index);
|
||||
uint8_t cstate = lswFamily(cs->func);
|
||||
|
||||
// V1
|
||||
auto line = logicalSwitchOneWindow->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_V1, 0, COLOR_THEME_PRIMARY1);
|
||||
switch (cstate) {
|
||||
case LS_FAMILY_BOOL:
|
||||
case LS_FAMILY_STICKY:
|
||||
case LS_FAMILY_EDGE:
|
||||
choice = new SwitchChoice(
|
||||
line, rect_t{}, SWSRC_FIRST_IN_LOGICAL_SWITCHES,
|
||||
SWSRC_LAST_IN_LOGICAL_SWITCHES, GET_SET_DEFAULT(cs->v1));
|
||||
choice->setAvailableHandler(isSwitchAvailableInLogicalSwitches);
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V2, 0, COLOR_THEME_PRIMARY1);
|
||||
choice = new SwitchChoice(logicalSwitchOneWindow, grid.getFieldSlot(), SWSRC_FIRST_IN_LOGICAL_SWITCHES, SWSRC_LAST_IN_LOGICAL_SWITCHES, GET_SET_DEFAULT(cs->v2));
|
||||
choice->setAvailableHandler(isSwitchAvailableInLogicalSwitches);
|
||||
grid.nextLine();
|
||||
}
|
||||
else if (cstate == LS_FAMILY_EDGE) {
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V1, 0, COLOR_THEME_PRIMARY1);
|
||||
auto choice = new SwitchChoice(logicalSwitchOneWindow, grid.getFieldSlot(), SWSRC_FIRST_IN_LOGICAL_SWITCHES, SWSRC_LAST_IN_LOGICAL_SWITCHES, GET_SET_DEFAULT(cs->v1));
|
||||
choice->setAvailableHandler(isSwitchAvailableInLogicalSwitches);
|
||||
grid.nextLine();
|
||||
|
||||
auto edit1 = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(2, 0), -129, 122, GET_DEFAULT(cs->v2));
|
||||
auto edit2 = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(2, 1), -1, 222 - cs->v2, GET_SET_DEFAULT(cs->v3));
|
||||
edit1->setSetValueHandler([=](int32_t newValue) {
|
||||
cs->v2 = newValue;
|
||||
SET_DIRTY();
|
||||
edit2->setMax(222 - cs->v2);
|
||||
edit2->setValue(cs->v3);
|
||||
});
|
||||
edit1->setDisplayHandler([](int32_t value) {
|
||||
return formatNumberAsString(lswTimerValue(value), PREC1);
|
||||
});
|
||||
edit2->setDisplayHandler([cs](int32_t value) {
|
||||
if (value < 0)
|
||||
return std::string("<<");
|
||||
else if (value == 0)
|
||||
return std::string("--");
|
||||
else {
|
||||
return formatNumberAsString(lswTimerValue(cs->v2 + value), PREC1);
|
||||
}
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
else if (cstate == LS_FAMILY_COMP) {
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V1, 0, COLOR_THEME_PRIMARY1);
|
||||
new SourceChoice(logicalSwitchOneWindow, grid.getFieldSlot(), 0, MIXSRC_LAST_TELEM, GET_SET_DEFAULT(cs->v1));
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V2, 0, COLOR_THEME_PRIMARY1);
|
||||
new SourceChoice(logicalSwitchOneWindow, grid.getFieldSlot(), 0, MIXSRC_LAST_TELEM, GET_SET_DEFAULT(cs->v2));
|
||||
grid.nextLine();
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V1, 0, COLOR_THEME_PRIMARY1);
|
||||
auto timer = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(), -128, 122, GET_SET_DEFAULT(cs->v1));
|
||||
break;
|
||||
case LS_FAMILY_COMP:
|
||||
new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST_TELEM,
|
||||
GET_SET_DEFAULT(cs->v1));
|
||||
break;
|
||||
case LS_FAMILY_TIMER:
|
||||
timer =
|
||||
new NumberEdit(line, rect_t{}, -128, 122, GET_SET_DEFAULT(cs->v1));
|
||||
timer->setDisplayHandler([](int32_t value) {
|
||||
return formatNumberAsString(lswTimerValue(value), PREC1);
|
||||
return formatNumberAsString(lswTimerValue(value), PREC1, 0, nullptr,
|
||||
"s");
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V2, 0, COLOR_THEME_PRIMARY1);
|
||||
timer = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(), -128, 122, GET_SET_DEFAULT(cs->v2));
|
||||
timer->setDisplayHandler([](int32_t value) {
|
||||
return formatNumberAsString(lswTimerValue(value), PREC1);
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
else {
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V1, 0, COLOR_THEME_PRIMARY1);
|
||||
new SourceChoice(logicalSwitchOneWindow, grid.getFieldSlot(), 0, MIXSRC_LAST_TELEM, GET_DEFAULT(cs->v1),
|
||||
[=](int32_t newValue) {
|
||||
break;
|
||||
default:
|
||||
new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST_TELEM,
|
||||
GET_DEFAULT(cs->v1), [=](int32_t newValue) {
|
||||
cs->v1 = newValue;
|
||||
if (v2Edit != nullptr)
|
||||
{
|
||||
if (v2Edit != nullptr) {
|
||||
int16_t v2_min = 0, v2_max = 0;
|
||||
getMixSrcRange(cs->v1, v2_min, v2_max);
|
||||
v2Edit->setMin(v2_min);
|
||||
@@ -177,97 +135,267 @@ class LogicalSwitchEditPage: public Page
|
||||
}
|
||||
SET_DIRTY();
|
||||
});
|
||||
grid.nextLine();
|
||||
break;
|
||||
}
|
||||
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V2, 0, COLOR_THEME_PRIMARY1);
|
||||
// V2
|
||||
if (cstate == LS_FAMILY_EDGE) {
|
||||
line = logicalSwitchOneWindow->newLine(&grid2);
|
||||
} else {
|
||||
line = logicalSwitchOneWindow->newLine(&grid);
|
||||
}
|
||||
new StaticText(line, rect_t{}, STR_V2, 0, COLOR_THEME_PRIMARY1);
|
||||
switch (cstate) {
|
||||
case LS_FAMILY_BOOL:
|
||||
case LS_FAMILY_STICKY:
|
||||
choice = new SwitchChoice(
|
||||
line, rect_t{}, SWSRC_FIRST_IN_LOGICAL_SWITCHES,
|
||||
SWSRC_LAST_IN_LOGICAL_SWITCHES, GET_SET_DEFAULT(cs->v2));
|
||||
choice->setAvailableHandler(isSwitchAvailableInLogicalSwitches);
|
||||
break;
|
||||
case LS_FAMILY_EDGE: {
|
||||
auto edit1 =
|
||||
new NumberEdit(line, rect_t{}, -129, 122, GET_DEFAULT(cs->v2));
|
||||
auto edit2 = new NumberEdit(line, rect_t{}, -1, 222 - cs->v2,
|
||||
GET_SET_DEFAULT(cs->v3));
|
||||
edit1->setSetValueHandler([=](int32_t newValue) {
|
||||
cs->v2 = newValue;
|
||||
SET_DIRTY();
|
||||
edit2->setMax(222 - cs->v2);
|
||||
edit2->setValue(cs->v3);
|
||||
});
|
||||
edit1->setDisplayHandler([](int32_t value) {
|
||||
return formatNumberAsString(lswTimerValue(value), PREC1, 0, nullptr,
|
||||
"s");
|
||||
});
|
||||
edit2->setDisplayHandler([cs](int32_t value) {
|
||||
if (value < 0)
|
||||
return std::string("<<");
|
||||
else if (value == 0)
|
||||
return std::string("--");
|
||||
else {
|
||||
return formatNumberAsString(lswTimerValue(cs->v2 + value), PREC1, 0,
|
||||
nullptr, "s");
|
||||
}
|
||||
});
|
||||
} break;
|
||||
case LS_FAMILY_COMP:
|
||||
new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST_TELEM,
|
||||
GET_SET_DEFAULT(cs->v2));
|
||||
break;
|
||||
case LS_FAMILY_TIMER:
|
||||
timer =
|
||||
new NumberEdit(line, rect_t{}, -128, 122, GET_SET_DEFAULT(cs->v2));
|
||||
timer->setDisplayHandler([](int32_t value) {
|
||||
return formatNumberAsString(lswTimerValue(value), PREC1, 0, nullptr,
|
||||
"s");
|
||||
});
|
||||
break;
|
||||
default:
|
||||
int16_t v2_min = 0, v2_max = 0;
|
||||
getMixSrcRange(cs->v1, v2_min, v2_max);
|
||||
v2Edit = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(),
|
||||
v2_min, v2_max, GET_SET_DEFAULT(cs->v2));
|
||||
v2Edit = new NumberEdit(line, rect_t{}, v2_min, v2_max,
|
||||
GET_SET_DEFAULT(cs->v2));
|
||||
lv_obj_set_width(v2Edit->getLvObj(), LV_SIZE_CONTENT);
|
||||
|
||||
v2Edit->setDisplayHandler([=](int value) -> std::string {
|
||||
if (cs->v1 <= MIXSRC_LAST_CH) value = calc100toRESX(value);
|
||||
std::string txt = getSourceCustomValueString(cs->v1, value, 0);
|
||||
return txt;
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
// AND switch
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_AND_SWITCH, 0, COLOR_THEME_PRIMARY1);
|
||||
auto choice = new SwitchChoice(logicalSwitchOneWindow, grid.getFieldSlot(), -MAX_LS_ANDSW, MAX_LS_ANDSW, GET_SET_DEFAULT(cs->andsw));
|
||||
choice->setAvailableHandler(isSwitchAvailableInLogicalSwitches);
|
||||
grid.nextLine();
|
||||
|
||||
// Duration
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_DURATION, 0, COLOR_THEME_PRIMARY1);
|
||||
auto edit = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(), 0, MAX_LS_DURATION, GET_SET_DEFAULT(cs->duration), 0, PREC1);
|
||||
edit->setZeroText("---");
|
||||
grid.nextLine();
|
||||
|
||||
// Delay
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_DELAY, 0, COLOR_THEME_PRIMARY1);
|
||||
if (cstate == LS_FAMILY_EDGE) {
|
||||
new StaticText(logicalSwitchOneWindow, grid.getFieldSlot(), STR_NA, 0, COLOR_THEME_PRIMARY1);
|
||||
}
|
||||
else {
|
||||
auto edit = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(), 0, MAX_LS_DELAY, GET_SET_DEFAULT(cs->delay), 0, PREC1);
|
||||
edit->setZeroText("---");
|
||||
}
|
||||
grid.nextLine();
|
||||
break;
|
||||
}
|
||||
|
||||
void buildBody(FormWindow * window)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
// AND switch
|
||||
line = logicalSwitchOneWindow->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_AND_SWITCH, 0, COLOR_THEME_PRIMARY1);
|
||||
choice = new SwitchChoice(line, rect_t{}, -MAX_LS_ANDSW, MAX_LS_ANDSW,
|
||||
GET_SET_DEFAULT(cs->andsw));
|
||||
choice->setAvailableHandler(isSwitchAvailableInLogicalSwitches);
|
||||
|
||||
LogicalSwitchData * cs = lswAddress(index);
|
||||
// Duration
|
||||
line = logicalSwitchOneWindow->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_DURATION, 0, COLOR_THEME_PRIMARY1);
|
||||
auto edit = new NumberEdit(line, rect_t{}, 0, MAX_LS_DURATION,
|
||||
GET_SET_DEFAULT(cs->duration), 0, PREC1);
|
||||
edit->setZeroText("---");
|
||||
edit->setDisplayHandler([](int32_t value) {
|
||||
return formatNumberAsString(value, PREC1, 0, nullptr, "s");
|
||||
});
|
||||
|
||||
// LS Func
|
||||
new StaticText(window, grid.getLabelSlot(), STR_FUNC, 0, COLOR_THEME_PRIMARY1);
|
||||
auto functionChoice = new Choice(window, grid.getFieldSlot(), STR_VCSWFUNC, 0, LS_FUNC_MAX, GET_DEFAULT(cs->func));
|
||||
functionChoice->setSetValueHandler([=](int32_t newValue) {
|
||||
cs->func = newValue;
|
||||
if (lswFamily(cs->func) == LS_FAMILY_TIMER) {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
else if (lswFamily(cs->func) == LS_FAMILY_EDGE) {
|
||||
cs->v1 = 0;
|
||||
cs->v2 = -129;
|
||||
cs->v3 = 0;
|
||||
}
|
||||
else {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
SET_DIRTY();
|
||||
updateLogicalSwitchOneWindow();
|
||||
// Delay
|
||||
line = logicalSwitchOneWindow->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_DELAY, 0, COLOR_THEME_PRIMARY1);
|
||||
if (cstate == LS_FAMILY_EDGE) {
|
||||
new StaticText(line, rect_t{}, STR_NA, 0, COLOR_THEME_PRIMARY1);
|
||||
} else {
|
||||
auto edit = new NumberEdit(line, rect_t{}, 0, MAX_LS_DELAY,
|
||||
GET_SET_DEFAULT(cs->delay), 0, PREC1);
|
||||
edit->setDisplayHandler([](int32_t value) {
|
||||
if (value == 0) return std::string("---");
|
||||
return formatNumberAsString(value, PREC1, 0, nullptr, "s");
|
||||
});
|
||||
functionChoice->setAvailableHandler(isLogicalSwitchFunctionAvailable);
|
||||
grid.nextLine();
|
||||
|
||||
logicalSwitchOneWindow = new FormGroup(window, { 0, grid.getWindowHeight(), LCD_W, 0 }// , FORM_FORWARD_FOCUS
|
||||
);
|
||||
updateLogicalSwitchOneWindow();
|
||||
grid.addWindow(logicalSwitchOneWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void buildBody(FormWindow* window)
|
||||
{
|
||||
window->setFlexLayout();
|
||||
FlexGridLayout grid(col_dsc, row_dsc, 2);
|
||||
lv_obj_set_style_pad_all(window->getLvObj(), lv_dpx(8), 0);
|
||||
|
||||
LogicalSwitchData* cs = lswAddress(index);
|
||||
|
||||
// LS Func
|
||||
auto line = window->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_FUNC, 0, COLOR_THEME_PRIMARY1);
|
||||
auto functionChoice = new Choice(line, rect_t{}, STR_VCSWFUNC, 0,
|
||||
LS_FUNC_MAX, GET_DEFAULT(cs->func));
|
||||
functionChoice->setSetValueHandler([=](int32_t newValue) {
|
||||
cs->func = newValue;
|
||||
if (lswFamily(cs->func) == LS_FAMILY_TIMER) {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
} else if (lswFamily(cs->func) == LS_FAMILY_EDGE) {
|
||||
cs->v1 = 0;
|
||||
cs->v2 = -129;
|
||||
cs->v3 = 0;
|
||||
} else {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
SET_DIRTY();
|
||||
updateLogicalSwitchOneWindow();
|
||||
});
|
||||
functionChoice->setAvailableHandler(isLogicalSwitchFunctionAvailable);
|
||||
|
||||
logicalSwitchOneWindow = new FormWindow(window, rect_t{});
|
||||
updateLogicalSwitchOneWindow();
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr coord_t line1 = FIELD_PADDING_TOP;
|
||||
static constexpr coord_t line2 = line1 + PAGE_LINE_HEIGHT;
|
||||
static constexpr coord_t col1 = 20;
|
||||
static constexpr coord_t col2 = (LCD_W - 100) / 3 + col1;
|
||||
static constexpr coord_t col3 = ((LCD_W - 100) / 3) * 2 + col1;
|
||||
void getsEdgeDelayParam(char* s, LogicalSwitchData* ls)
|
||||
{
|
||||
sprintf(s, "[%s:%s]",
|
||||
formatNumberAsString(lswTimerValue(ls->v2), PREC1, 0, nullptr, "s")
|
||||
.c_str(),
|
||||
(ls->v3 < 0) ? "<<"
|
||||
: (ls->v3 == 0) ? "--"
|
||||
: formatNumberAsString(lswTimerValue(ls->v2 + ls->v3),
|
||||
PREC1, 0, nullptr, "s")
|
||||
.c_str());
|
||||
}
|
||||
|
||||
#if LCD_W > LCD_H // Landscape
|
||||
|
||||
#define TXT_ALIGN LV_GRID_ALIGN_CENTER
|
||||
|
||||
static const lv_coord_t b_col_dsc[] = {36, 50, 88, 92,
|
||||
88, 40, 40, LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
static const lv_coord_t b_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
#define NM_ROW_CNT 1
|
||||
#define ANDSW_ROW 0
|
||||
#define ANDSW_COL 4
|
||||
|
||||
#else // Portrait
|
||||
|
||||
#define TXT_ALIGN LV_GRID_ALIGN_START
|
||||
|
||||
static const lv_coord_t b_col_dsc[] = {36, LV_GRID_FR(1), 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};
|
||||
|
||||
#define NM_ROW_CNT 2
|
||||
#define ANDSW_ROW 1
|
||||
#define ANDSW_COL 1
|
||||
|
||||
#endif
|
||||
|
||||
class LogicalSwitchButton : public Button
|
||||
{
|
||||
public:
|
||||
LogicalSwitchButton(FormGroup* parent, const rect_t& rect, int lsIndex) :
|
||||
Button(parent, rect, nullptr, 0, COLOR_THEME_PRIMARY1), lsIndex(lsIndex), active(isActive())
|
||||
LogicalSwitchButton(Window* parent, const rect_t& rect, int lsIndex) :
|
||||
Button(parent, rect, nullptr, 0, 0, input_mix_line_create),
|
||||
lsIndex(lsIndex)
|
||||
{
|
||||
LogicalSwitchData* ls = lswAddress(lsIndex);
|
||||
if (ls->andsw != SWSRC_NONE || ls->duration != 0 || ls->delay != 0)
|
||||
setHeight(height() + 20);
|
||||
#if LCD_H > LCD_W
|
||||
padTop(0);
|
||||
#endif
|
||||
padLeft(3);
|
||||
padRight(3);
|
||||
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);
|
||||
|
||||
check(isActive());
|
||||
|
||||
lv_obj_update_layout(parent->getLvObj());
|
||||
if (lv_obj_is_visible(lvobj)) delayed_init(nullptr);
|
||||
|
||||
lv_obj_add_event_cb(lvobj, LogicalSwitchButton::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 = (LogicalSwitchButton*)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)
|
||||
{
|
||||
lsName = lv_label_create(lvobj);
|
||||
lv_obj_set_style_text_align(lsName, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_grid_cell(lsName, LV_GRID_ALIGN_STRETCH, 0, 1,
|
||||
LV_GRID_ALIGN_CENTER, 0, NM_ROW_CNT);
|
||||
|
||||
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, 1, 1,
|
||||
LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
|
||||
lsV1 = lv_label_create(lvobj);
|
||||
lv_obj_set_style_text_align(lsV1, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_set_grid_cell(lsV1, LV_GRID_ALIGN_STRETCH, 2, 1,
|
||||
LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
|
||||
lsV2 = lv_label_create(lvobj);
|
||||
lv_obj_set_style_text_align(lsV2, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_set_grid_cell(lsV2, LV_GRID_ALIGN_STRETCH, 3, 1,
|
||||
LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
|
||||
lsAnd = lv_label_create(lvobj);
|
||||
lv_obj_set_style_text_align(lsAnd, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_set_grid_cell(lsAnd, LV_GRID_ALIGN_STRETCH, ANDSW_COL, 1,
|
||||
LV_GRID_ALIGN_CENTER, ANDSW_ROW, 1);
|
||||
|
||||
lsDuration = lv_label_create(lvobj);
|
||||
lv_obj_set_style_text_align(lsDuration, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_set_grid_cell(lsDuration, LV_GRID_ALIGN_STRETCH, ANDSW_COL + 1, 1,
|
||||
LV_GRID_ALIGN_CENTER, ANDSW_ROW, 1);
|
||||
|
||||
lsDelay = lv_label_create(lvobj);
|
||||
lv_obj_set_style_text_align(lsDelay, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_set_grid_cell(lsDelay, LV_GRID_ALIGN_STRETCH, ANDSW_COL + 2, 1,
|
||||
LV_GRID_ALIGN_CENTER, ANDSW_ROW, 1);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool isActive() const
|
||||
@@ -277,171 +405,288 @@ class LogicalSwitchButton : public Button
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
if (active != isActive()) {
|
||||
invalidate();
|
||||
active = !active;
|
||||
}
|
||||
|
||||
Button::checkEvents();
|
||||
check(isActive());
|
||||
}
|
||||
|
||||
void paintLogicalSwitchLine(BitmapBuffer* dc)
|
||||
void refresh()
|
||||
{
|
||||
if (!init) return;
|
||||
|
||||
char s[20];
|
||||
|
||||
LogicalSwitchData* ls = lswAddress(lsIndex);
|
||||
uint8_t lsFamily = lswFamily(ls->func);
|
||||
|
||||
// CSW func
|
||||
dc->drawTextAtIndex(col1, line1, STR_VCSWFUNC, ls->func, COLOR_THEME_SECONDARY1);
|
||||
lv_label_set_text(lsName, getSwitchPositionName(SWSRC_SW1 + lsIndex));
|
||||
lv_label_set_text(lsFunc, STR_VCSWFUNC[ls->func]);
|
||||
|
||||
// CSW params
|
||||
if (lsFamily == LS_FAMILY_BOOL || lsFamily == LS_FAMILY_STICKY) {
|
||||
drawSwitch(dc, col2, line1, ls->v1, COLOR_THEME_SECONDARY1);
|
||||
drawSwitch(dc, col3, line1, ls->v2, COLOR_THEME_SECONDARY1);
|
||||
} else if (lsFamily == LS_FAMILY_EDGE) {
|
||||
drawSwitch(dc, col2, line1, ls->v1, COLOR_THEME_SECONDARY1);
|
||||
putsEdgeDelayParam(dc, col3, line1, ls, COLOR_THEME_SECONDARY1);
|
||||
} else if (lsFamily == LS_FAMILY_COMP) {
|
||||
drawSource(dc, col2, line1, ls->v1, COLOR_THEME_SECONDARY1);
|
||||
drawSource(dc, col3, line1, ls->v2, COLOR_THEME_SECONDARY1);
|
||||
} else if (lsFamily == LS_FAMILY_TIMER) {
|
||||
dc->drawNumber(col2, line1, lswTimerValue(ls->v1), COLOR_THEME_SECONDARY1 | LEFT | PREC1);
|
||||
dc->drawNumber(col3, line1, lswTimerValue(ls->v2), COLOR_THEME_SECONDARY1 | LEFT | PREC1);
|
||||
} else {
|
||||
drawSource(dc, col2, line1, ls->v1, COLOR_THEME_SECONDARY1);
|
||||
drawSourceCustomValue(dc, col3, line1, ls->v1,
|
||||
(ls->v1 <= MIXSRC_LAST_CH ? calc100toRESX(ls->v2) : ls->v2), COLOR_THEME_SECONDARY1);
|
||||
// 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
|
||||
drawSwitch(dc, col1, line2, ls->andsw, COLOR_THEME_SECONDARY1);
|
||||
lv_label_set_text(lsAnd, getSwitchPositionName(ls->andsw));
|
||||
|
||||
// CSW duration
|
||||
if (ls->duration > 0) {
|
||||
dc->drawNumber(col2, line2, ls->duration, COLOR_THEME_SECONDARY1 | PREC1 | LEFT);
|
||||
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) {
|
||||
dc->drawNumber(col3, line2, ls->delay, COLOR_THEME_SECONDARY1 | PREC1 | LEFT);
|
||||
lv_label_set_text(
|
||||
lsDelay,
|
||||
formatNumberAsString(ls->delay, PREC1, 0, nullptr, "s").c_str());
|
||||
} else {
|
||||
lv_label_set_text(lsDelay, "");
|
||||
}
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer* dc) override
|
||||
{
|
||||
if (active)
|
||||
dc->drawSolidFilledRect(0, 0, rect.w, rect.h, COLOR_THEME_ACTIVE);
|
||||
else
|
||||
dc->drawSolidFilledRect(0, 0, rect.w, rect.h, COLOR_THEME_PRIMARY2);
|
||||
|
||||
paintLogicalSwitchLine(dc);
|
||||
|
||||
// The bounding rect
|
||||
if (hasFocus())
|
||||
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, COLOR_THEME_FOCUS);
|
||||
else
|
||||
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, COLOR_THEME_SECONDARY2);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool init = false;
|
||||
uint8_t lsIndex;
|
||||
bool active;
|
||||
|
||||
lv_obj_t* lsName = nullptr;
|
||||
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;
|
||||
};
|
||||
|
||||
ModelLogicalSwitchesPage::ModelLogicalSwitchesPage():
|
||||
PageTab(STR_MENULOGICALSWITCHES, ICON_MODEL_LOGICAL_SWITCHES)
|
||||
#if LCD_W > LCD_H
|
||||
#define LS_BUTTON_H 34
|
||||
#else
|
||||
#define LS_BUTTON_H 45
|
||||
#endif
|
||||
|
||||
ModelLogicalSwitchesPage::ModelLogicalSwitchesPage() :
|
||||
PageTab(STR_MENULOGICALSWITCHES, ICON_MODEL_LOGICAL_SWITCHES)
|
||||
{
|
||||
}
|
||||
|
||||
void ModelLogicalSwitchesPage::rebuild(FormWindow * window, int8_t focusIndex)
|
||||
void ModelLogicalSwitchesPage::rebuild(FormWindow* window)
|
||||
{
|
||||
auto scroll_y = lv_obj_get_scroll_y(window->getLvObj());
|
||||
// When window.clear() is called the last button on screen is given focus
|
||||
// (???) This causes the page to jump to the end when rebuilt. Set flag to
|
||||
// bypass the button focus handler and reset focusIndex when rebuilding
|
||||
isRebuilding = true;
|
||||
window->clear();
|
||||
build(window, focusIndex);
|
||||
lv_obj_scroll_to_y(window->getLvObj(), scroll_y, LV_ANIM_OFF);
|
||||
build(window);
|
||||
isRebuilding = false;
|
||||
}
|
||||
|
||||
void ModelLogicalSwitchesPage::editLogicalSwitch(FormWindow * window, uint8_t lsIndex)
|
||||
void ModelLogicalSwitchesPage::newLS(FormWindow* window, bool pasteLS)
|
||||
{
|
||||
Window * lsWindow = new LogicalSwitchEditPage(lsIndex);
|
||||
lsWindow->setCloseHandler([=]() {
|
||||
rebuild(window, lsIndex);
|
||||
});
|
||||
Menu* menu = new Menu(Layer::back());
|
||||
menu->setTitle(STR_MENU_LOGICAL_SWITCHES);
|
||||
|
||||
// search for unused switches
|
||||
for (uint8_t i = 0; i < MAX_LOGICAL_SWITCHES; i++) {
|
||||
LogicalSwitchData* ls = lswAddress(i);
|
||||
if (ls->func == LS_FUNC_NONE) {
|
||||
std::string ch_name(getSwitchPositionName(SWSRC_SW1 + i));
|
||||
menu->addLineBuffered(ch_name.c_str(), [=]() {
|
||||
if (pasteLS) {
|
||||
*ls = clipboard.data.csw;
|
||||
storageDirty(EE_MODEL);
|
||||
focusIndex = i;
|
||||
rebuild(window);
|
||||
} else {
|
||||
Window* lsWindow = new LogicalSwitchEditPage(i);
|
||||
lsWindow->setCloseHandler([=]() {
|
||||
if (ls->func != LS_FUNC_NONE) {
|
||||
focusIndex = i;
|
||||
rebuild(window);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
menu->updateLines();
|
||||
}
|
||||
|
||||
void ModelLogicalSwitchesPage::build(FormWindow* window, int8_t focusIndex)
|
||||
void ModelLogicalSwitchesPage::plusPopup(FormWindow* window)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
grid.setLabelWidth(66);
|
||||
window->padAll(0);
|
||||
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH) {
|
||||
Menu* menu = new Menu(window);
|
||||
menu->addLine(STR_NEW, [=]() { newLS(window, false); });
|
||||
menu->addLine(STR_PASTE, [=]() { newLS(window, true); });
|
||||
} else {
|
||||
newLS(window, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelLogicalSwitchesPage::build(FormWindow* window)
|
||||
{
|
||||
#if LCD_W > LCD_H
|
||||
#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
|
||||
|
||||
window->padAll(4);
|
||||
|
||||
auto form = new FormWindow(window, rect_t{});
|
||||
form->setFlexLayout();
|
||||
form->padAll(0);
|
||||
|
||||
FlexGridLayout grid(l_col_dsc, row_dsc, 2);
|
||||
|
||||
FormWindow::Line* line;
|
||||
bool hasEmptySwitch = false;
|
||||
Button* button;
|
||||
|
||||
// Reset focusIndex after switching tabs
|
||||
if (!isRebuilding) focusIndex = prevFocusIndex;
|
||||
|
||||
for (uint8_t i = 0; i < MAX_LOGICAL_SWITCHES; i++) {
|
||||
LogicalSwitchData* ls = lswAddress(i);
|
||||
|
||||
if (ls->func == LS_FUNC_NONE) {
|
||||
auto button = new TextButton(window, grid.getLabelSlot(),
|
||||
getSwitchPositionName(SWSRC_SW1 + i));
|
||||
button->setPressHandler([=]() {
|
||||
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH) {
|
||||
Menu* menu = new Menu(window);
|
||||
menu->addLine(STR_EDIT, [=]() { editLogicalSwitch(window, i); });
|
||||
menu->addLine(STR_PASTE, [=]() {
|
||||
*ls = clipboard.data.csw;
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, i);
|
||||
});
|
||||
} else {
|
||||
editLogicalSwitch(window, i);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
grid.spacer(button->height() + 5);
|
||||
} else {
|
||||
auto txt = new StaticText(window, grid.getLabelSlot(),
|
||||
getSwitchPositionName(SWSRC_SW1 + i),
|
||||
BUTTON_BACKGROUND, COLOR_THEME_PRIMARY1 | CENTERED);
|
||||
bool isActive = (ls->func != LS_FUNC_NONE);
|
||||
|
||||
if (isActive) {
|
||||
line = form->newLine(&grid);
|
||||
|
||||
button = new LogicalSwitchButton(
|
||||
line, rect_t{0, 0, window->width() - 12, LS_BUTTON_H}, i);
|
||||
|
||||
lv_obj_set_grid_cell(button->getLvObj(), LV_GRID_ALIGN_CENTER, 0, PER_ROW,
|
||||
LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
|
||||
auto button = new LogicalSwitchButton(window, grid.getFieldSlot(), i);
|
||||
button->setPressHandler([=]() {
|
||||
Menu* menu = new Menu(window);
|
||||
menu->addLine(STR_EDIT, [=]() { editLogicalSwitch(window, i); });
|
||||
if (ls->func)
|
||||
menu->addLine(STR_EDIT, [=]() {
|
||||
Window* lsWindow = new LogicalSwitchEditPage(i);
|
||||
lsWindow->setCloseHandler([=]() {
|
||||
if (isActive)
|
||||
lv_event_send(button->getLvObj(), LV_EVENT_VALUE_CHANGED,
|
||||
nullptr);
|
||||
else
|
||||
rebuild(window);
|
||||
});
|
||||
});
|
||||
if (isActive) {
|
||||
menu->addLine(STR_COPY, [=]() {
|
||||
clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH;
|
||||
clipboard.data.csw = *ls;
|
||||
});
|
||||
}
|
||||
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH)
|
||||
menu->addLine(STR_PASTE, [=]() {
|
||||
*ls = clipboard.data.csw;
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, i);
|
||||
rebuild(window);
|
||||
});
|
||||
if (ls->func || ls->v1 || ls->v2 || ls->delay || ls->duration ||
|
||||
ls->andsw)
|
||||
if (isActive || ls->v1 || ls->v2 || ls->delay || ls->duration ||
|
||||
ls->andsw) {
|
||||
menu->addLine(STR_CLEAR, [=]() {
|
||||
memset(ls, 0, sizeof(LogicalSwitchData));
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, i);
|
||||
rebuild(window);
|
||||
});
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
button->setFocusHandler([=](bool focus) {
|
||||
if (focus) {
|
||||
txt->setBackgroundColor(COLOR_THEME_FOCUS);
|
||||
txt->setTextFlags(COLOR_THEME_PRIMARY2 | CENTERED);
|
||||
} else {
|
||||
txt->setBackgroundColor(COLOR_THEME_SECONDARY2);
|
||||
txt->setTextFlags(COLOR_THEME_PRIMARY1 | CENTERED);
|
||||
|
||||
if (focusIndex == i) {
|
||||
lv_group_focus_obj(button->getLvObj());
|
||||
}
|
||||
|
||||
button->setLongPressHandler([=]() -> uint8_t {
|
||||
if (addButton) {
|
||||
lv_group_focus_obj(addButton->getLvObj());
|
||||
plusPopup(window);
|
||||
}
|
||||
txt->invalidate();
|
||||
return 0;
|
||||
});
|
||||
|
||||
txt->setHeight(button->height());
|
||||
grid.spacer(button->height() + 5);
|
||||
button->setFocusHandler([=](bool hasFocus) {
|
||||
if (hasFocus && !isRebuilding) {
|
||||
prevFocusIndex = focusIndex;
|
||||
focusIndex = i;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
hasEmptySwitch = true;
|
||||
}
|
||||
}
|
||||
|
||||
grid.nextLine();
|
||||
if (hasEmptySwitch) {
|
||||
line = form->newLine(&grid);
|
||||
addButton =
|
||||
new TextButton(line, rect_t{0, 0, window->width() - 12, LS_BUTTON_H},
|
||||
LV_SYMBOL_PLUS, [=]() {
|
||||
plusPopup(window);
|
||||
return 0;
|
||||
});
|
||||
|
||||
addButton->setLongPressHandler([=]() -> uint8_t {
|
||||
plusPopup(window);
|
||||
return 0;
|
||||
});
|
||||
|
||||
addButton->setFocusHandler([=](bool hasFocus) {
|
||||
if (hasFocus && !isRebuilding) {
|
||||
prevFocusIndex = focusIndex;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
addButton = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,19 +24,22 @@
|
||||
|
||||
#include "tabsgroup.h"
|
||||
|
||||
class ModelLogicalSwitchesPage: public PageTab {
|
||||
public:
|
||||
ModelLogicalSwitchesPage();
|
||||
class ModelLogicalSwitchesPage : public PageTab
|
||||
{
|
||||
public:
|
||||
ModelLogicalSwitchesPage();
|
||||
|
||||
virtual void build(FormWindow * window) override
|
||||
{
|
||||
build(window, 0);
|
||||
}
|
||||
virtual void build(FormWindow* window) override;
|
||||
|
||||
protected:
|
||||
void build(FormWindow * window, int8_t focusIndex);
|
||||
void rebuild(FormWindow * window, int8_t focusIndex);
|
||||
void editLogicalSwitch(FormWindow * window, uint8_t lsIndex);
|
||||
protected:
|
||||
int8_t focusIndex = -1;
|
||||
int8_t prevFocusIndex = -1;
|
||||
bool isRebuilding = false;
|
||||
Button* addButton = nullptr;
|
||||
|
||||
void rebuild(FormWindow* window);
|
||||
void newLS(FormWindow* window, bool pasteLS);
|
||||
void plusPopup(FormWindow* window);
|
||||
};
|
||||
|
||||
#endif //_MODEL_LOGICAL_SWITCHES_H
|
||||
#endif //_MODEL_LOGICAL_SWITCHES_H
|
||||
|
||||
@@ -21,75 +21,284 @@
|
||||
|
||||
#include "opentx.h"
|
||||
#include "view_logical_switches.h"
|
||||
#include "gridlayout.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#if LCD_W > LCD_H // Landscape
|
||||
#define BTN_MATRIX_COL 8
|
||||
#else // Portrait
|
||||
#define BTN_MATRIX_COL 4
|
||||
#if LCD_W > LCD_H // Landscape
|
||||
|
||||
#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_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,
|
||||
std::string text, unsigned index) :
|
||||
TextButton(parent, rect, std::move(text), nullptr, OPAQUE), index(index)
|
||||
{
|
||||
}
|
||||
public:
|
||||
LogicalSwitchDisplayButton(Window* parent, const rect_t& rect,
|
||||
std::string text, unsigned index) :
|
||||
TextButton(parent, rect, std::move(text), nullptr, OPAQUE), index(index)
|
||||
{
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
bool newvalue = getSwitch(SWSRC_SW1 + index);
|
||||
if (value != newvalue) {
|
||||
if (newvalue) {
|
||||
lv_obj_add_state(lvobj, LV_STATE_CHECKED);
|
||||
} else {
|
||||
lv_obj_clear_state(lvobj, LV_STATE_CHECKED);
|
||||
}
|
||||
value = newvalue;
|
||||
invalidate();
|
||||
}
|
||||
Button::checkEvents();
|
||||
}
|
||||
void checkEvents() override
|
||||
{
|
||||
bool newvalue = getSwitch(SWSRC_SW1 + index);
|
||||
if (value != newvalue) {
|
||||
if (newvalue) {
|
||||
lv_obj_add_state(lvobj, LV_STATE_CHECKED);
|
||||
} else {
|
||||
lv_obj_clear_state(lvobj, LV_STATE_CHECKED);
|
||||
}
|
||||
value = newvalue;
|
||||
invalidate();
|
||||
}
|
||||
Button::checkEvents();
|
||||
}
|
||||
|
||||
protected:
|
||||
unsigned index = 0;
|
||||
bool value = false;
|
||||
protected:
|
||||
unsigned index = 0;
|
||||
bool value = false;
|
||||
};
|
||||
|
||||
void LogicalSwitchesViewPage::build(FormWindow * window)
|
||||
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});
|
||||
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);
|
||||
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;
|
||||
});
|
||||
if ((i + 1) % BTN_MATRIX_COL == 0) grid.nextLine();
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,92 +25,17 @@
|
||||
#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
|
||||
{
|
||||
public:
|
||||
LogicalSwitchesViewPage() :
|
||||
public:
|
||||
LogicalSwitchesViewPage() :
|
||||
PageTab(STR_MONITOR_SWITCHES, ICON_MONITOR_LOGICAL_SWITCHES)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void build(FormWindow * window) override;
|
||||
LogicalSwitchDisplayFooter * footer = nullptr;
|
||||
protected:
|
||||
void build(FormWindow* window) override;
|
||||
LogicalSwitchDisplayFooter* footer = nullptr;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user