chore(color): LVGLify custom mixer scripts page (#3071)

* LVGL flex conversion for custom mixer scripts.

* Adjust spacing for portrait layout and widest text value.
This commit is contained in:
philmoz
2023-02-05 11:31:32 +10:00
committed by GitHub
parent 8d00dc8803
commit 4e09bd7b8c
+136 -89
View File
@@ -28,11 +28,31 @@
#include "translations.h"
#include "menus.h"
#include "libopenui.h"
#include <string.h>
#include "lvgl_widgets/input_mix_line.h"
#define SET_DIRTY() storageDirty(EE_MODEL)
// Overview grid
static const lv_coord_t col_dsc[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
// Edit grid
#if LCD_W > LCD_H
static const lv_coord_t e_col_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(3),
LV_GRID_TEMPLATE_LAST};
#else
static const lv_coord_t e_col_dsc[] = {LV_GRID_FR(5), LV_GRID_FR(4),
LV_GRID_TEMPLATE_LAST};
#endif
// Line button grid
static const lv_coord_t b_col_dsc[] = {40, 84, 84, LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST
};
static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
class ScriptEditWindow : public Page {
public:
explicit ScriptEditWindow(uint8_t idx) :
@@ -69,17 +89,21 @@ class ScriptEditWindow : public Page {
void buildBody(FormWindow * window, bool focusScript = false)
{
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
auto form = new FormWindow(window, rect_t{});
form->setFlexLayout();
form->padAll(4);
FlexGridLayout grid(e_col_dsc, row_dsc, 2);
// the general pattern seems to be using capture-by-value for the closures: so need to copy the pointers, not the objects
ScriptData* const sd = &(g_model.scriptsData[idx]);
ScriptInputsOutputs* const sio = &(scriptInputsOutputs[idx]);
bool* const updatePtr = &update;
new StaticText(window, grid.getLabelSlot(), STR_SCRIPT, 0, COLOR_THEME_PRIMARY1);
// File
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_SCRIPT, 0, COLOR_THEME_PRIMARY1);
auto fc = new FileChoice(
window, grid.getFieldSlot(), SCRIPTS_MIXES_PATH, SCRIPTS_EXT,
line, rect_t{}, SCRIPTS_MIXES_PATH, SCRIPTS_EXT,
LEN_SCRIPT_FILENAME,
[=]() { return stringFromNtString(sd->file); },
[=](std::string newValue) {
@@ -90,61 +114,48 @@ class ScriptEditWindow : public Page {
}
storageDirty(EE_MODEL);
LUA_LOAD_MODEL_SCRIPT(idx); // async reload ...
*updatePtr = true; // TODO: sets update==true and afterwards calls rebuildBody() via checkEvents()
update = true;
}, true);
grid.nextLine();
// Custom name
new StaticText(window, grid.getLabelSlot(), STR_NAME, 0, COLOR_THEME_PRIMARY1);
new ModelTextEdit(window, grid.getFieldSlot(), sd->name, sizeof(sd->name));
grid.nextLine();
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_NAME, 0, COLOR_THEME_PRIMARY1);
new ModelTextEdit(line, rect_t{}, sd->name, sizeof(sd->name));
if (sio->inputsCount > 0) {
new Subtitle(window, grid.getLineSlot(), STR_INPUTS, 0, COLOR_THEME_PRIMARY1);
grid.nextLine();
auto gInputs = new FormGroup(window, grid.getFieldSlot(), FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
GridLayout inputsGrid(gInputs);
line = form->newLine(&grid);
new Subtitle(line, rect_t{}, STR_INPUTS, 0, COLOR_THEME_PRIMARY1);
for (int i = 0; i < sio->inputsCount; i++) {
line = form->newLine(&grid);
ScriptInput& si = sio->inputs[i];
new StaticText(window, grid.getLabelSlot(true), si.name, 0, COLOR_THEME_PRIMARY1);
grid.nextLine();
auto lbl = new StaticText(line, rect_t{}, si.name, 0, COLOR_THEME_PRIMARY1);
lbl->padLeft(10);
if (si.type == INPUT_TYPE_VALUE) {
(new NumberEdit(gInputs, inputsGrid.getSlot(), si.min, si.max,
(new NumberEdit(line, rect_t{}, si.min, si.max,
GET_SET_WITH_OFFSET(sd->inputs[i].value, si.def)))->setDefault(si.def);
} else {
new SourceChoice(gInputs, inputsGrid.getSlot(), 0,
MIXSRC_LAST_TELEM,
new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST_TELEM,
GET_SET_DEFAULT(sd->inputs[i].source));
}
inputsGrid.nextLine();
}
gInputs->setHeight(inputsGrid.getWindowHeight());
}
if (sio->outputsCount > 0) {
new Subtitle(window, grid.getLabelSlot(), STR_OUTPUTS, 0, COLOR_THEME_PRIMARY1);
grid.nextLine();
auto gOutputs =
new FormGroup(window, grid.getLineSlot(),
FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
FormGridLayout outputsGrid(gOutputs->width());
line = form->newLine(&grid);
new Subtitle(line, rect_t{}, STR_OUTPUTS, 0, COLOR_THEME_PRIMARY1);
for (int i = 0; i < sio->outputsCount; i++) {
line = form->newLine(&grid);
ScriptOutput* so = &(sio->outputs[i]);
new DynamicText(gOutputs, outputsGrid.getLabelSlot(), [=]() {
auto lbl = new DynamicText(line, rect_t{}, [=]() {
char s[16];
getSourceString(s, MIXSRC_FIRST_LUA + (idx * MAX_SCRIPT_OUTPUTS) + i);
return std::string(s, sizeof(s) - 1);
}, COLOR_THEME_PRIMARY1);
new DynamicNumber<int16_t>(gOutputs, outputsGrid.getFieldSlot(), [=]() { return calcRESXto1000(so->value); }, COLOR_THEME_PRIMARY1);
outputsGrid.nextLine();
lbl->padLeft(10);
new DynamicNumber<int16_t>(line, rect_t{}, [=]() { return calcRESXto1000(so->value); }, COLOR_THEME_PRIMARY1);
}
gOutputs->setHeight(outputsGrid.getWindowHeight());
grid.addWindow(gOutputs);
}
}
@@ -160,61 +171,112 @@ class ScriptEditWindow : public Page {
class ScriptLineButton : public Button
{
public:
ScriptLineButton(FormGroup* parent, const rect_t& rect,
ScriptLineButton(Window* parent, const rect_t& rect,
const ScriptData& scriptData,
const ScriptInternalData* runtimeData) :
Button(parent, rect), scriptData(scriptData), runtimeData(runtimeData)
const ScriptInternalData* runtimeData,
uint8_t index) :
Button(parent, rect, nullptr, 0, 0, input_mix_line_create),
scriptData(scriptData),
runtimeData(runtimeData),
index(index)
{
#if LCD_H > LCD_W
padTop(5);
#endif
padLeft(3);
padRight(3);
lv_obj_set_layout(lvobj, LV_LAYOUT_GRID);
lv_obj_set_grid_dsc_array(lvobj, b_col_dsc, row_dsc);
lv_obj_set_style_pad_row(lvobj, 0, 0);
lv_obj_set_style_pad_column(lvobj, 4, 0);
lv_obj_update_layout(parent->getLvObj());
if(lv_obj_is_visible(lvobj)) delayed_init(nullptr);
lv_obj_add_event_cb(lvobj, ScriptLineButton::on_draw, LV_EVENT_DRAW_MAIN_BEGIN, nullptr);
}
void paint(BitmapBuffer* dc) override
static void on_draw(lv_event_t * e)
{
LcdFlags textColor = COLOR_THEME_SECONDARY1;
LcdFlags bgColor = COLOR_THEME_PRIMARY2;
lv_obj_t* target = lv_event_get_target(e);
auto line = (ScriptLineButton*)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)
{
auto lbl = lv_label_create(lvobj);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lbl, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1);
dc->drawSolidFilledRect(0, 0, width(), height(), bgColor);
lv_label_set_text(lbl, (std::string("LUA") + std::to_string(index + 1)).c_str());
if (runtimeData) {
coord_t x = 2*FIELD_PADDING_LEFT;
coord_t y = FIELD_PADDING_TOP;
char s[20];
x = dc->drawSizedText(x, y, scriptData.name, sizeof(scriptData.name), textColor);
x += 4*FIELD_PADDING_LEFT;
lbl = lv_label_create(lvobj);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lbl, LV_GRID_ALIGN_START, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
dc->drawSizedText(x, y, scriptData.file, sizeof(scriptData.file), textColor);
strAppend(s, scriptData.name, LEN_SCRIPT_NAME);
lv_label_set_text(lbl, s);
lbl = lv_label_create(lvobj);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lbl, LV_GRID_ALIGN_START, 2, 1, LV_GRID_ALIGN_CENTER, 0, 1);
strAppend(s, scriptData.file, LEN_SCRIPT_FILENAME);
lv_label_set_text(lbl, s);
lbl = lv_label_create(lvobj);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lbl, LV_GRID_ALIGN_START, 3, 1, LV_GRID_ALIGN_CENTER, 0, 1);
x = width() - 2*FIELD_PADDING_LEFT;
y = FIELD_PADDING_TOP;
textColor |= RIGHT;
// TODO: runtimeData->instructions has no value
switch (runtimeData->state) {
case SCRIPT_SYNTAX_ERROR:
dc->drawSizedText(x, y, STR_SCRIPT_ERROR, strlen(STR_SCRIPT_ERROR), textColor);
lv_label_set_text(lbl, STR_SCRIPT_ERROR);
break;
case SCRIPT_NOFILE:
dc->drawSizedText(x, y, STR_NEEDS_FILE, strlen(STR_NEEDS_FILE), textColor);
case SCRIPT_NOFILE:
lv_label_set_text(lbl, STR_NEEDS_FILE);
break;
case SCRIPT_OK:
dc->drawSizedText(x, y, "-", 1, textColor);
case SCRIPT_OK:
lv_label_set_text(lbl, "-");
break;
default:
default:
lv_label_set_text(lbl, "");
break;
}
}
// 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);
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()
{
}
protected:
bool init = false;
uint8_t index;
const ScriptData& scriptData;
const ScriptInternalData* runtimeData;
};
#define CM_BUTTON_H 34
ModelMixerScriptsPage::ModelMixerScriptsPage() :
PageTab(STR_MENUCUSTOMSCRIPTS, ICON_MODEL_LUA_SCRIPTS)
{
@@ -230,13 +292,19 @@ void ModelMixerScriptsPage::rebuild(FormWindow * window, int8_t focusIdx)
void ModelMixerScriptsPage::build(FormWindow * window, int8_t focusIdx)
{
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
grid.setLabelWidth(66);
window->padAll(0);
auto form = new FormWindow(window, rect_t{});
form->setFlexLayout();
form->padAll(4);
FlexGridLayout grid(col_dsc, row_dsc, 2);
FormWindow::Line* line;
int8_t scriptIdx = 0;
for (int8_t idx = 0; idx < MAX_SCRIPTS; idx++) {
auto line = form->newLine(&grid);
ScriptInternalData* runtimeData = nullptr;
ScriptData* const sd = &(g_model.scriptsData[idx]);
@@ -246,12 +314,7 @@ void ModelMixerScriptsPage::build(FormWindow * window, int8_t focusIdx)
runtimeData = &(scriptInternalData[scriptIdx++]);
}
// LUAx label
auto const txt = new StaticText(window, grid.getLabelSlot(),
std::string("LUA") + std::to_string(idx + 1),
BUTTON_BACKGROUND, COLOR_THEME_PRIMARY1 | CENTERED);
Button* const button = new ScriptLineButton(window, grid.getFieldSlot(), *sd, runtimeData);
Button* const button = new ScriptLineButton(line, rect_t{0, 0, window->width() - 12, CM_BUTTON_H}, *sd, runtimeData, idx);
button->setPressHandler([=]() -> uint8_t {
Menu* const menu = new Menu(window);
@@ -269,23 +332,7 @@ void ModelMixerScriptsPage::build(FormWindow * window, int8_t focusIdx)
}
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);
}
txt->invalidate();
});
txt->setHeight(button->height());
grid.spacer(button->height() + 5);
}
grid.nextLine();
}
void ModelMixerScriptsPage::editLine(FormWindow * window, uint8_t idx)