feat: Interactive/progressive preflight checklist (#3564)
* initial version of clickable checklist * do not display checkboxes for empty lines if checklist is shorter than screen size * remove checklist exit after completing it cannot exit menu from menuTextView as level above there is while loop that cannot be stopped from thic place in code * menu entry to enable and disable interactive checklist * only when complete interactive checklist is closed * config updated & not display checkboxes when entered from "View Notes" * add setup entry for colorlcd * do not make interactive checkist when loaded from menu * fix datastruct size after merge * Companion support for interactive checklist * mark checklist lines as non-checkable with '=' for B&W radios * Process only items visible on screen This is also crucial when it comes to analyse non-checkable items on a checklist, as in this way there is no need to load non-visible items from SD-card * WIP fix merge problems * update yaml datastructs * restore most functionalities for interactive check lists on color LCD radios currently no automatic line wrapping and you can always exit the checklist, even when it is not fully done * finalise interactive checklists for color LCD * fix: rebase/merge issues * fix: model setup checklist section * fix: fix 212 model setup * Re-work of the some of the color lcd checklist code (#3787) * Move checklist logic to sub-class. Show model name instead of file name in title, show 'Preflight checks' in title2 for checklist. Handle long line wrapping of text. Don't indent lines without checkbox. Add 'RTN' button when done. * Code cleanup. * Simplify code by storing a list of checkboxes instead of scanning LVGL object hierarchy. * Indent checkboxes to make touch activation easier. Keep 'RTN' button visible so last checkbox is further from bottom of screen (for touch activation). 'RTN' button is disabled until checklist complete. * Add checkbox class constructor for preflight checks. * Fix checkbox size. --------- Co-authored-by: Piotr Rzeszut <piotrrze@gmail.com> Co-authored-by: 3djc <lesitewebdejc@hotmail.com> Co-authored-by: philmoz <philmoz@users.noreply.github.com> Co-authored-by: Phil Mitchell <phil.a.mitchell@gmail.com>
This commit is contained in:
co-authored by
Piotr Rzeszut
3djc
philmoz
Phil Mitchell
parent
ceba62650e
commit
06712d9b97
@@ -920,6 +920,7 @@ Node convert<ModelData>::encode(const ModelData& rhs)
|
||||
node["extendedLimits"] = (int)rhs.extendedLimits;
|
||||
node["extendedTrims"] = (int)rhs.extendedTrims;
|
||||
node["throttleReversed"] = (int)rhs.throttleReversed;
|
||||
node["checklistInteractive"] = (int)rhs.checklistInteractive;
|
||||
|
||||
for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) {
|
||||
if (!rhs.flightModeData[i].isEmpty(i)) {
|
||||
@@ -1201,6 +1202,7 @@ bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
|
||||
node["extendedLimits"] >> rhs.extendedLimits;
|
||||
node["extendedTrims"] >> rhs.extendedTrims;
|
||||
node["throttleReversed"] >> rhs.throttleReversed;
|
||||
node["checklistInteractive"] >> rhs.checklistInteractive;
|
||||
|
||||
node["flightModeData"] >> rhs.flightModeData;
|
||||
node["mixData"] >> rhs.mixData;
|
||||
|
||||
@@ -145,6 +145,7 @@ class ModelData {
|
||||
bool extendedLimits; // TODO xml
|
||||
bool extendedTrims;
|
||||
bool throttleReversed;
|
||||
bool checklistInteractive;
|
||||
FlightModeData flightModeData[CPN_MAX_FLIGHT_MODES];
|
||||
MixData mixData[CPN_MAX_MIXERS];
|
||||
LimitData limitData[CPN_MAX_CHNOUT];
|
||||
|
||||
@@ -1797,6 +1797,7 @@ void SetupPanel::update()
|
||||
ui->extendedLimits->setChecked(model->extendedLimits);
|
||||
ui->extendedTrims->setChecked(model->extendedTrims);
|
||||
ui->displayText->setChecked(model->displayChecklist);
|
||||
ui->checklistInteractive->setChecked(model->checklistInteractive);
|
||||
ui->gfEnabled->setChecked(!model->noGlobalFunctions);
|
||||
ui->jitterFilter->setCurrentIndex(model->jitterFilter);
|
||||
|
||||
@@ -1944,6 +1945,12 @@ void SetupPanel::on_displayText_toggled(bool checked)
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void SetupPanel::on_checklistInteractive_toggled(bool checked)
|
||||
{
|
||||
model->checklistInteractive = checked;
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void SetupPanel::on_gfEnabled_toggled(bool checked)
|
||||
{
|
||||
model->noGlobalFunctions = !checked;
|
||||
|
||||
@@ -191,6 +191,7 @@ class SetupPanel : public ModelPanel
|
||||
void on_customThrottleWarningPosition_valueChanged(int value);
|
||||
void on_throttleReverse_toggled(bool checked);
|
||||
void on_displayText_toggled(bool checked);
|
||||
void on_checklistInteractive_toggled(bool checked);
|
||||
void on_gfEnabled_toggled(bool checked);
|
||||
void on_image_currentIndexChanged(int index);
|
||||
void on_trimIncrement_currentIndexChanged(int index);
|
||||
|
||||
@@ -579,6 +579,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QCheckBox" name="checklistInteractive">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interactive Checklist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QLabel" name="label_jitterFilter">
|
||||
<property name="font">
|
||||
|
||||
@@ -678,7 +678,8 @@ PACK(struct ModelData {
|
||||
uint8_t enableCustomThrottleWarning:1;
|
||||
uint8_t disableTelemetryWarning:1;
|
||||
uint8_t showInstanceIds:1;
|
||||
uint8_t spare3:5 SKIP;
|
||||
uint8_t checklistInteractive:1;
|
||||
uint8_t spare3:4 SKIP; // padding to 8-bit aligment
|
||||
int8_t customThrottleWarningPosition;
|
||||
BeepANACenter beepANACenter;
|
||||
MixData mixData[MAX_MIXERS] NO_IDX;
|
||||
|
||||
@@ -99,6 +99,7 @@ enum MenuModelSetupItems {
|
||||
ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH,
|
||||
ITEM_MODEL_SETUP_PREFLIGHT_LABEL,
|
||||
ITEM_MODEL_SETUP_CHECKLIST_DISPLAY,
|
||||
ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE,
|
||||
ITEM_MODEL_SETUP_THROTTLE_WARNING,
|
||||
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING,
|
||||
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING_VALUE,
|
||||
@@ -584,6 +585,7 @@ void menuModelSetup(event_t event)
|
||||
|
||||
0, // Preflight section
|
||||
PREFLIGHT_ROW(0), // Checklist
|
||||
PREFLIGHT_ROW(0), // Checklist interactive
|
||||
PREFLIGHT_ROW(0), // Throttle warning
|
||||
PREFLIGHT_ROW(0), // Custom position for throttle warning enable
|
||||
PREFLIGHT_ROW(0), // Custom position for throttle warning value
|
||||
@@ -923,6 +925,10 @@ void menuModelSetup(event_t event)
|
||||
case ITEM_MODEL_SETUP_CHECKLIST_DISPLAY:
|
||||
g_model.displayChecklist = editCheckBox(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE:
|
||||
g_model.checklistInteractive = editCheckBox(g_model.checklistInteractive, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST_INTERACTIVE, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_SETUP_THROTTLE_WARNING:
|
||||
g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLE_WARNING, attr, event);
|
||||
|
||||
@@ -87,6 +87,7 @@ enum MenuModelSetupItems {
|
||||
ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH,
|
||||
ITEM_MODEL_SETUP_PREFLIGHT_LABEL,
|
||||
ITEM_MODEL_SETUP_CHECKLIST_DISPLAY,
|
||||
ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE,
|
||||
ITEM_MODEL_SETUP_THROTTLE_WARNING,
|
||||
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING,
|
||||
ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING_VALUE,
|
||||
@@ -528,6 +529,7 @@ void menuModelSetup(event_t event)
|
||||
|
||||
0, // Preflight section
|
||||
PREFLIGHT_ROW(0), // Checklist
|
||||
PREFLIGHT_ROW(0), // Checklist interactive
|
||||
PREFLIGHT_ROW(0), // Throttle warning
|
||||
PREFLIGHT_ROW(0), // Custom position for throttle warning enable
|
||||
PREFLIGHT_ROW(0), // Custom position for throttle warning value
|
||||
@@ -819,6 +821,10 @@ void menuModelSetup(event_t event)
|
||||
case ITEM_MODEL_SETUP_CHECKLIST_DISPLAY:
|
||||
g_model.displayChecklist = editCheckBox(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE:
|
||||
g_model.checklistInteractive = editCheckBox(g_model.checklistInteractive, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST_INTERACTIVE, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_SETUP_THROTTLE_WARNING:
|
||||
g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLE_WARNING, attr, event);
|
||||
|
||||
@@ -118,7 +118,18 @@ PreflightChecks::PreflightChecks() : Page(ICON_MODEL_SETUP)
|
||||
// Display checklist
|
||||
auto line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_CHECKLIST, 0, COLOR_THEME_PRIMARY1);
|
||||
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();
|
||||
chkList->setSetValueHandler([=](int32_t newValue) {
|
||||
g_model.displayChecklist = newValue; SET_DIRTY();
|
||||
(g_model.displayChecklist)?interactiveChkList->enable():interactiveChkList->disable();
|
||||
});
|
||||
|
||||
// Throttle warning
|
||||
line = form->newLine(&grid);
|
||||
|
||||
@@ -82,7 +82,7 @@ typedef struct {
|
||||
// Choice
|
||||
lv_style_t choice_main;
|
||||
|
||||
// Checkbox
|
||||
// Toggle switch
|
||||
lv_style_t switch_knob;
|
||||
|
||||
// Table
|
||||
@@ -103,6 +103,10 @@ typedef struct {
|
||||
lv_style_t progress_main;
|
||||
lv_style_t progress_indicator;
|
||||
|
||||
// Check Box
|
||||
lv_style_t cb_marker;
|
||||
lv_style_t cb_marker_checked;
|
||||
|
||||
} my_theme_styles_t;
|
||||
|
||||
/**********************
|
||||
@@ -237,7 +241,7 @@ static void style_init(void)
|
||||
lv_style_init(&styles.bg_color_transparent);
|
||||
lv_style_set_bg_opa(&styles.bg_color_transparent, LV_OPA_TRANSP);
|
||||
|
||||
// Checkbox and slider knob rounding
|
||||
// Toggle switch and slider knob rounding
|
||||
lv_style_init(&styles.circle);
|
||||
lv_style_set_radius(&styles.circle, LV_RADIUS_CIRCLE);
|
||||
|
||||
@@ -265,7 +269,7 @@ static void style_init(void)
|
||||
lv_style_init(&styles.anim_fast);
|
||||
lv_style_set_anim_time(&styles.anim_fast, 120);
|
||||
|
||||
// Checkbox
|
||||
// Toggle switch
|
||||
lv_style_init(&styles.switch_knob);
|
||||
lv_style_set_pad_all(&styles.switch_knob, -3);
|
||||
lv_style_set_bg_opa(&styles.switch_knob, LV_OPA_100);
|
||||
@@ -315,6 +319,14 @@ static void style_init(void)
|
||||
// Text align
|
||||
lv_style_init(&styles.text_align_right);
|
||||
lv_style_set_text_align(&styles.text_align_right, LV_TEXT_ALIGN_RIGHT);
|
||||
|
||||
// Check Box
|
||||
lv_style_init(&styles.cb_marker);
|
||||
lv_style_set_bg_opa(&styles.cb_marker, LV_OPA_COVER);
|
||||
lv_style_set_pad_all(&styles.cb_marker, lv_disp_dpx(theme.disp, 3));
|
||||
lv_style_init(&styles.cb_marker_checked);
|
||||
lv_style_set_bg_img_src(&styles.cb_marker_checked, LV_SYMBOL_OK);
|
||||
lv_style_set_text_font(&styles.cb_marker_checked, theme.font_small);
|
||||
}
|
||||
|
||||
// Always update colors in case theme changes
|
||||
@@ -377,6 +389,12 @@ static void style_init(void)
|
||||
|
||||
lv_style_set_bg_color(&styles.progress_main, makeLvColor(COLOR_THEME_SECONDARY2));
|
||||
lv_style_set_bg_color(&styles.progress_indicator, makeLvColor(COLOR_THEME_SECONDARY1));
|
||||
|
||||
lv_style_set_border_color(&styles.cb_marker, makeLvColor(COLOR_THEME_SECONDARY2));
|
||||
lv_style_set_bg_color(&styles.cb_marker, makeLvColor(COLOR_THEME_PRIMARY2));
|
||||
lv_style_set_border_color(&styles.cb_marker_checked, makeLvColor(COLOR_THEME_SECONDARY1));
|
||||
lv_style_set_bg_color(&styles.cb_marker_checked, makeLvColor(COLOR_THEME_SECONDARY1));
|
||||
lv_style_set_text_color(&styles.cb_marker_checked, makeLvColor(COLOR_THEME_PRIMARY2));
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -569,6 +587,17 @@ void etx_bar_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
lv_obj_add_style(obj, &styles.rounded, LV_PART_INDICATOR);
|
||||
}
|
||||
|
||||
void etx_checkbox_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_add_style(obj, &styles.rounded, LV_PART_INDICATOR);
|
||||
lv_obj_add_style(obj, &styles.pad_zero, LV_PART_INDICATOR);
|
||||
lv_obj_add_style(obj, &styles.cb_marker, LV_PART_INDICATOR);
|
||||
lv_obj_add_style(obj, &styles.cb_marker_checked, LV_PART_INDICATOR | LV_STATE_CHECKED);
|
||||
lv_obj_add_style(obj, &styles.border, LV_PART_INDICATOR);
|
||||
lv_obj_add_style(obj, &styles.focussed, LV_PART_INDICATOR | LV_STATE_FOCUSED);
|
||||
lv_obj_add_style(obj, &styles.disabled, LV_PART_INDICATOR | LV_STATE_DISABLED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Object classes
|
||||
@@ -754,6 +783,19 @@ const lv_obj_class_t etx_bar_class = {
|
||||
.instance_size = sizeof(lv_bar_t),
|
||||
};
|
||||
|
||||
const lv_obj_class_t etx_checkbox_class = {
|
||||
.base_class = &lv_checkbox_class,
|
||||
.constructor_cb = etx_checkbox_constructor,
|
||||
.destructor_cb = nullptr,
|
||||
.user_data = nullptr,
|
||||
.event_cb = nullptr,
|
||||
.width_def = lv_pct(100),
|
||||
.height_def = lv_pct(100),
|
||||
.editable = LV_OBJ_CLASS_EDITABLE_INHERIT,
|
||||
.group_def = LV_OBJ_CLASS_GROUP_DEF_INHERIT,
|
||||
.instance_size = sizeof(lv_checkbox_t),
|
||||
};
|
||||
|
||||
// Event handlers
|
||||
static void field_edit_event(const lv_obj_class_t* class_p, lv_event_t* e)
|
||||
{
|
||||
@@ -876,6 +918,11 @@ lv_obj_t* etx_bar_create(lv_obj_t* parent)
|
||||
return etx_create(&etx_bar_class, parent);
|
||||
}
|
||||
|
||||
lv_obj_t* etx_checkbox_create(lv_obj_t* parent)
|
||||
{
|
||||
return etx_create(&etx_checkbox_class, parent);
|
||||
}
|
||||
|
||||
lv_obj_t* etx_modal_create(lv_obj_t* parent)
|
||||
{
|
||||
lv_obj_t* obj = window_create(parent);
|
||||
|
||||
@@ -55,7 +55,7 @@ ViewMainMenu::ViewMainMenu(Window* parent, std::function<void()> closeHandler) :
|
||||
if (modelHasNotes()) {
|
||||
carousel->addButton(ICON_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES, [=]() -> uint8_t {
|
||||
deleteLater();
|
||||
readModelNotes();
|
||||
readModelNotes(true);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,6 +24,35 @@
|
||||
#include "opentx.h"
|
||||
#include "sdcard.h"
|
||||
|
||||
constexpr int maxTxtBuffSize = 64 * 1024;
|
||||
|
||||
ViewTextWindow::ViewTextWindow(const std::string path, const std::string name,
|
||||
unsigned int icon) :
|
||||
Page(icon), path(std::move(path)), name(std::move(name))
|
||||
{
|
||||
fullPath = this->path + std::string(PATH_SEPARATOR) + this->name;
|
||||
extractNameSansExt();
|
||||
|
||||
header.setTitle(this->name);
|
||||
|
||||
lv_obj_add_event_cb(lvobj, ViewTextWindow::on_draw, LV_EVENT_DRAW_MAIN_BEGIN, nullptr);
|
||||
};
|
||||
|
||||
void ViewTextWindow::on_draw(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t* target = lv_event_get_target(e);
|
||||
auto view = (ViewTextWindow*)lv_obj_get_user_data(target);
|
||||
if (view) {
|
||||
if (view->buffer == nullptr)
|
||||
view->buildBody(&view->body);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewTextWindow::onCancel()
|
||||
{
|
||||
Page::onCancel();
|
||||
}
|
||||
|
||||
void ViewTextWindow::extractNameSansExt()
|
||||
{
|
||||
uint8_t nameLength;
|
||||
@@ -32,14 +61,11 @@ void ViewTextWindow::extractNameSansExt()
|
||||
const char *ext =
|
||||
getFileExtension(name.c_str(), 0, 0, &nameLength, &extLength);
|
||||
extension = std::string(ext);
|
||||
if (nameLength > TEXT_FILENAME_MAXLEN) nameLength = TEXT_FILENAME_MAXLEN;
|
||||
|
||||
nameLength -= extLength;
|
||||
name.substr(nameLength);
|
||||
openFromEnd = !strcmp(ext, LOGS_EXT);
|
||||
}
|
||||
|
||||
void ViewTextWindow::buildBody(Window *window)
|
||||
bool ViewTextWindow::openFile()
|
||||
{
|
||||
FILINFO info;
|
||||
|
||||
@@ -61,30 +87,39 @@ void ViewTextWindow::buildBody(Window *window)
|
||||
TRACE("info.fsize=%d\tbufSize=%d\toffset=%d", info.fsize, bufSize,
|
||||
int(info.fsize) - bufSize + 1);
|
||||
if (sdReadTextFileBlock(bufSize, offset) == FR_OK) {
|
||||
auto obj = window->getLvObj();
|
||||
lv_obj_add_flag(
|
||||
obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW |
|
||||
LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO);
|
||||
// prevents resetting the group's edit mode
|
||||
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
|
||||
auto g = lv_group_get_default();
|
||||
lb = lv_label_create(obj);
|
||||
lv_obj_set_size(lb, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_pad_all(lb, lv_dpx(8), 0);
|
||||
|
||||
lv_group_add_obj(g, obj);
|
||||
lv_group_set_editing(g, true);
|
||||
lv_label_set_text_static(lb, buffer);
|
||||
|
||||
if (openFromEnd)
|
||||
lv_obj_scroll_to_y(obj, LV_COORD_MAX, LV_ANIM_OFF);
|
||||
else
|
||||
lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ViewTextWindow::buildBody(Window *window)
|
||||
{
|
||||
if (openFile()) {
|
||||
auto obj = window->getLvObj();
|
||||
lv_obj_add_flag(
|
||||
obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW |
|
||||
LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO);
|
||||
// prevents resetting the group's edit mode
|
||||
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
|
||||
auto g = lv_group_get_default();
|
||||
lb = lv_label_create(obj);
|
||||
lv_obj_set_size(lb, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_pad_all(lb, lv_dpx(8), 0);
|
||||
|
||||
lv_group_add_obj(g, obj);
|
||||
lv_group_set_editing(g, true);
|
||||
lv_label_set_text_static(lb, buffer);
|
||||
|
||||
if (openFromEnd)
|
||||
lv_obj_scroll_to_y(obj, LV_COORD_MAX, LV_ANIM_OFF);
|
||||
else
|
||||
lv_obj_scroll_to_y(obj, 0, LV_ANIM_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
FRESULT ViewTextWindow::sdReadTextFileBlock(const uint32_t bufSize,
|
||||
@@ -172,10 +207,176 @@ void ViewTextWindow::onEvent(event_t event)
|
||||
sdReadTextFileBlock(bufSize, offset);
|
||||
lv_label_set_text_static(lb, buffer);
|
||||
}
|
||||
|
||||
if(event == EVT_KEY_BREAK(KEY_EXIT))
|
||||
onCancel();
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "datastructs.h"
|
||||
static void checkbox_event_handler(lv_event_t* e);
|
||||
|
||||
class ViewChecklistWindow : public ViewTextWindow
|
||||
{
|
||||
public:
|
||||
ViewChecklistWindow(const std::string path, const std::string name,
|
||||
unsigned int icon) :
|
||||
ViewTextWindow(path, name, icon)
|
||||
{
|
||||
header.setTitle(g_model.header.name);
|
||||
header.setTitle2(STR_PREFLIGHT);
|
||||
}
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override { return "ViewChecklistWindow"; };
|
||||
#endif
|
||||
|
||||
void onCancel() override
|
||||
{
|
||||
if (allChecked())
|
||||
ViewTextWindow::onCancel();
|
||||
}
|
||||
|
||||
protected:
|
||||
TextButton* closeButton = nullptr;
|
||||
std::list<lv_obj_t*> checkBoxes;
|
||||
|
||||
void updateCheckboxes()
|
||||
{
|
||||
bool lastState = true;
|
||||
|
||||
for (auto it = checkBoxes.cbegin(); it != checkBoxes.cend(); ++it) {
|
||||
auto cb = *it;
|
||||
if (lastState)
|
||||
{
|
||||
lv_obj_clear_state(cb, LV_STATE_DISABLED);
|
||||
if (!(lv_obj_get_state(cb) & LV_STATE_CHECKED))
|
||||
lv_group_focus_obj(cb);
|
||||
} else {
|
||||
lv_obj_add_state(cb, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(cb, LV_STATE_CHECKED);
|
||||
}
|
||||
|
||||
lastState = lv_obj_get_state(cb) & LV_STATE_CHECKED;
|
||||
}
|
||||
|
||||
setCloseState();
|
||||
}
|
||||
|
||||
bool allChecked()
|
||||
{
|
||||
for (auto it = checkBoxes.cbegin(); it != checkBoxes.cend(); ++it) {
|
||||
auto cb = *it;
|
||||
if (!(lv_obj_get_state(cb) & LV_STATE_CHECKED))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void setCloseState()
|
||||
{
|
||||
if (allChecked()) {
|
||||
lv_obj_clear_state(closeButton->getLvObj(), LV_STATE_DISABLED);
|
||||
lv_group_focus_obj(closeButton->getLvObj());
|
||||
} else {
|
||||
lv_obj_add_state(closeButton->getLvObj(), LV_STATE_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
void onEvent(event_t event) override
|
||||
{
|
||||
#if defined(HARDWARE_KEYS)
|
||||
if(event == EVT_KEY_BREAK(KEY_EXIT))
|
||||
onCancel();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void checkbox_event_handler(lv_event_t* e)
|
||||
{
|
||||
lv_obj_t* target = lv_event_get_target(e);
|
||||
ViewChecklistWindow* vtw = (ViewChecklistWindow*)lv_obj_get_user_data(target);
|
||||
|
||||
if (vtw) vtw->updateCheckboxes();
|
||||
}
|
||||
|
||||
void buildBody(Window* window) override
|
||||
{
|
||||
if (openFile()) {
|
||||
auto obj = window->getLvObj();
|
||||
lv_obj_add_flag(
|
||||
obj, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_WITH_ARROW |
|
||||
LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_AUTO);
|
||||
// prevents resetting the group's edit mode
|
||||
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
|
||||
lv_obj_set_layout(obj, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_style_pad_all(obj, 3, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_row(obj, 0, LV_PART_MAIN);
|
||||
|
||||
auto g = lv_group_get_default();
|
||||
|
||||
checkBoxes.clear();
|
||||
|
||||
size_t cur = 0;
|
||||
|
||||
for(int i=0; i<bufSize; ++i)
|
||||
{
|
||||
if (buffer[i] == '\n' || buffer[i] == '\r') {
|
||||
buffer[i] = 0;
|
||||
if (buffer[i] == '\r' && buffer[i+1] == '\n')
|
||||
i += 1;
|
||||
|
||||
lv_obj_t* row = lv_obj_create(obj);
|
||||
lv_obj_set_layout(row, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_width(row, lv_pct(100));
|
||||
lv_obj_set_height(row, LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_pad_all(row, 3, 0);
|
||||
lv_obj_set_style_pad_column(row, 6, 0);
|
||||
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_EVENLY);
|
||||
|
||||
lv_coord_t w = lv_obj_get_content_width(obj) - 6;
|
||||
|
||||
if (buffer[cur] == '=') {
|
||||
cur++;
|
||||
w -= 46;
|
||||
|
||||
lv_obj_set_style_pad_left(row, 10, 0);
|
||||
|
||||
auto cb = etx_checkbox_create(row);
|
||||
lv_checkbox_set_text_static(cb, "");
|
||||
lv_obj_set_width(cb, 25);
|
||||
lv_obj_set_height(cb, 25);
|
||||
|
||||
lv_group_add_obj(g, cb);
|
||||
|
||||
lv_obj_add_event_cb(cb, ViewChecklistWindow::checkbox_event_handler, LV_EVENT_VALUE_CHANGED, this);
|
||||
lv_obj_set_user_data(cb, this);
|
||||
|
||||
checkBoxes.push_back(cb);
|
||||
}
|
||||
|
||||
auto lbl = lv_label_create(row);
|
||||
lv_obj_set_width(lbl, w);
|
||||
lv_label_set_long_mode(lbl, LV_LABEL_LONG_WRAP);
|
||||
lv_label_set_text_static(lbl, &buffer[cur]);
|
||||
|
||||
cur = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto box = new FormWindow(window, rect_t{0, 0, lv_pct(100), LV_SIZE_CONTENT});
|
||||
box->padAll(8);
|
||||
|
||||
closeButton = new TextButton(box, rect_t{}, STR_EXIT, [=]() -> int8_t { this->onCancel(); return 0; });
|
||||
closeButton->setWidth(lv_pct(100));
|
||||
|
||||
updateCheckboxes();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void replaceSpaceWithUnderscore(std::string &name)
|
||||
{
|
||||
@@ -192,19 +393,22 @@ static void replaceSpaceWithUnderscore(std::string &name)
|
||||
#define MODEL_FILE_EXT MODELS_EXT
|
||||
#endif
|
||||
|
||||
bool openNotes(const char buf[], std::string modelNotesName)
|
||||
static bool openNotes(const char buf[], std::string modelNotesName, bool fromMenu = false)
|
||||
{
|
||||
std::string fullPath = std::string(buf) + PATH_SEPARATOR + modelNotesName;
|
||||
|
||||
if (isFileAvailable(fullPath.c_str())) {
|
||||
new ViewTextWindow(std::string(buf), modelNotesName, ICON_MODEL);
|
||||
if (fromMenu || !g_model.checklistInteractive)
|
||||
new ViewTextWindow(std::string(buf), modelNotesName, ICON_MODEL);
|
||||
else
|
||||
new ViewChecklistWindow(std::string(buf), modelNotesName, ICON_MODEL);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void readModelNotes()
|
||||
void readModelNotes(bool fromMenu)
|
||||
{
|
||||
bool notesFound = false;
|
||||
LED_ERROR_BEGIN();
|
||||
@@ -213,10 +417,10 @@ void readModelNotes()
|
||||
modelNotesName.append(TEXT_EXT);
|
||||
const char buf[] = {MODELS_PATH};
|
||||
|
||||
notesFound = openNotes(buf, modelNotesName);
|
||||
notesFound = openNotes(buf, modelNotesName, fromMenu);
|
||||
if (!notesFound) {
|
||||
replaceSpaceWithUnderscore(modelNotesName);
|
||||
notesFound = openNotes(buf, modelNotesName);
|
||||
notesFound = openNotes(buf, modelNotesName, fromMenu);
|
||||
}
|
||||
|
||||
#if !defined(EEPROM)
|
||||
@@ -226,11 +430,11 @@ void readModelNotes()
|
||||
if (index != std::string::npos) {
|
||||
modelNotesName.erase(index);
|
||||
modelNotesName.append(TEXT_EXT);
|
||||
notesFound = openNotes(buf, modelNotesName);
|
||||
notesFound = openNotes(buf, modelNotesName, fromMenu);
|
||||
}
|
||||
if (!notesFound) {
|
||||
replaceSpaceWithUnderscore(modelNotesName);
|
||||
notesFound = openNotes(buf, modelNotesName);
|
||||
notesFound = openNotes(buf, modelNotesName, fromMenu);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,29 +21,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "ff.h"
|
||||
#include "lcd.h"
|
||||
#include "menus.h"
|
||||
#include "page.h"
|
||||
#include "static.h"
|
||||
#include "sdcard.h"
|
||||
|
||||
#include "LvglWrapper.h"
|
||||
|
||||
constexpr int maxTxtBuffSize = 64 * 1024;
|
||||
|
||||
class ViewTextWindow : public Page
|
||||
{
|
||||
public:
|
||||
ViewTextWindow(const std::string path, const std::string name,
|
||||
unsigned int icon = ICON_RADIO_SD_MANAGER) :
|
||||
Page(icon), path(std::move(path)), name(std::move(name))
|
||||
{
|
||||
fullPath = this->path + std::string(PATH_SEPARATOR) + this->name;
|
||||
extractNameSansExt();
|
||||
|
||||
header.setTitle(this->name);
|
||||
buildBody(&body);
|
||||
};
|
||||
unsigned int icon = ICON_RADIO_SD_MANAGER);
|
||||
|
||||
FRESULT sdReadTextFileBlock(const uint32_t bufSize,
|
||||
const uint32_t offset);
|
||||
@@ -56,6 +41,8 @@ class ViewTextWindow : public Page
|
||||
}
|
||||
}
|
||||
|
||||
void onCancel() override;
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override { return "ViewTextWindow"; };
|
||||
#endif
|
||||
@@ -75,9 +62,13 @@ class ViewTextWindow : public Page
|
||||
bool openFromEnd;
|
||||
|
||||
void extractNameSansExt(void);
|
||||
void buildBody(Window* window);
|
||||
virtual void buildBody(Window* window);
|
||||
|
||||
bool openFile();
|
||||
|
||||
void onEvent(event_t event) override;
|
||||
|
||||
static void on_draw(lv_event_t * e);
|
||||
};
|
||||
|
||||
void readModelNotes();
|
||||
void readModelNotes(bool fromMenu = false);
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
void menuModelNotes(event_t event)
|
||||
@@ -34,7 +33,7 @@ void menuModelNotes(event_t event)
|
||||
strcpy(buf, TEXT_EXT);
|
||||
}
|
||||
}
|
||||
|
||||
reusableBuffer.viewText.pushMenu = true;
|
||||
menuTextView(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "opentx.h"
|
||||
|
||||
constexpr uint32_t TEXT_FILE_MAXSIZE = 2048;
|
||||
constexpr char NON_CHECKABLE_PREFIX = '=';
|
||||
int checklistPosition;
|
||||
|
||||
static void sdReadTextFile(const char * filename, char lines[TEXT_VIEWER_LINES][LCD_COLS + 1], int & lines_count)
|
||||
{
|
||||
@@ -102,7 +104,8 @@ void readModelNotes()
|
||||
|
||||
waitKeysReleased();
|
||||
event_t event = EVT_ENTRY;
|
||||
while (event != EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
reusableBuffer.viewText.pushMenu = false;
|
||||
while (true) {
|
||||
uint32_t power = pwrCheck();
|
||||
if (power != e_power_press) {
|
||||
lcdRefreshWait();
|
||||
@@ -117,6 +120,7 @@ void readModelNotes()
|
||||
}
|
||||
event = getEvent();
|
||||
WDG_RESET();
|
||||
if (reusableBuffer.viewText.checklistComplete) break;
|
||||
}
|
||||
|
||||
LED_ERROR_END();
|
||||
@@ -126,6 +130,8 @@ void menuTextView(event_t event)
|
||||
{
|
||||
if (event == EVT_ENTRY) {
|
||||
menuVerticalOffset = 0;
|
||||
checklistPosition = 0;
|
||||
reusableBuffer.viewText.checklistComplete = false;
|
||||
reusableBuffer.viewText.linesCount = 0;
|
||||
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
|
||||
} else if (IS_PREVIOUS_EVENT(event)) {
|
||||
@@ -138,12 +144,51 @@ void menuTextView(event_t event)
|
||||
++menuVerticalOffset;
|
||||
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
|
||||
}
|
||||
} else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
if (g_model.checklistInteractive && !reusableBuffer.viewText.pushMenu && checklistPosition-(int)menuVerticalOffset >= 0){
|
||||
if (checklistPosition < reusableBuffer.viewText.linesCount) {
|
||||
if (checklistPosition-(int)menuVerticalOffset < LCD_LINES-1) {
|
||||
++checklistPosition;
|
||||
if (checklistPosition-(int)menuVerticalOffset >= LCD_LINES-2 && menuVerticalOffset+LCD_LINES-1 < reusableBuffer.viewText.linesCount) {
|
||||
++menuVerticalOffset;
|
||||
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (reusableBuffer.viewText.pushMenu == true) popMenu();
|
||||
reusableBuffer.viewText.checklistComplete = true;
|
||||
}
|
||||
}
|
||||
} else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
popMenu();
|
||||
if (!g_model.checklistInteractive || reusableBuffer.viewText.pushMenu) {
|
||||
if (reusableBuffer.viewText.pushMenu == true) popMenu();
|
||||
reusableBuffer.viewText.checklistComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<LCD_LINES-1; i++) {
|
||||
lcdDrawText(0, i*FH+FH+1, reusableBuffer.viewText.lines[i], FIXEDWIDTH);
|
||||
if (g_model.checklistInteractive){
|
||||
if (reusableBuffer.viewText.lines[i][0] == NON_CHECKABLE_PREFIX) {
|
||||
lcdDrawText(8, i*FH+FH+1, &reusableBuffer.viewText.lines[i][1], FIXEDWIDTH);
|
||||
if (i == checklistPosition-(int)menuVerticalOffset){
|
||||
++checklistPosition;
|
||||
if (checklistPosition-(int)menuVerticalOffset == LCD_LINES-1 && menuVerticalOffset+LCD_LINES-1 < reusableBuffer.viewText.linesCount) {
|
||||
++menuVerticalOffset;
|
||||
sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount);
|
||||
i = 0; // Reset rendering of the display after changing the offest
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (i < reusableBuffer.viewText.linesCount && !reusableBuffer.viewText.pushMenu)
|
||||
drawCheckBox(0, i*FH+FH+1, i < checklistPosition-(int)menuVerticalOffset, i == checklistPosition-(int)menuVerticalOffset);
|
||||
lcdDrawText(8, i*FH+FH+1, reusableBuffer.viewText.lines[i], FIXEDWIDTH);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawText(0, i*FH+FH+1, reusableBuffer.viewText.lines[i], FIXEDWIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
char * title = reusableBuffer.viewText.filename;
|
||||
@@ -164,6 +209,7 @@ void pushMenuTextView(const char *filename)
|
||||
{
|
||||
if (strlen(filename) < TEXT_FILENAME_MAXLEN) {
|
||||
strcpy(reusableBuffer.viewText.filename, filename);
|
||||
reusableBuffer.viewText.pushMenu = true;
|
||||
pushMenu(menuTextView);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -975,6 +975,8 @@ union ReusableBuffer
|
||||
char filename[TEXT_FILENAME_MAXLEN];
|
||||
char lines[NUM_BODY_LINES][LCD_COLS + 1];
|
||||
int linesCount;
|
||||
bool checklistComplete;
|
||||
bool pushMenu;
|
||||
} viewText;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -788,7 +788,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -818,7 +818,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -786,7 +786,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -786,7 +786,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -825,7 +825,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -825,7 +825,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -789,7 +789,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -789,7 +789,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -786,7 +786,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -792,7 +792,8 @@ static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
|
||||
YAML_UNSIGNED( "showInstanceIds", 1 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "checklistInteractive", 1 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
|
||||
@@ -40,6 +40,7 @@ lv_obj_t* etx_modal_create(lv_obj_t* parent);
|
||||
lv_obj_t* etx_modal_content_create(lv_obj_t* parent);
|
||||
lv_obj_t* etx_modal_title_create(lv_obj_t* parent);
|
||||
lv_obj_t* etx_bar_create(lv_obj_t* parent);
|
||||
lv_obj_t* etx_checkbox_create(lv_obj_t* parent);
|
||||
|
||||
lv_obj_t* input_mix_line_create(lv_obj_t* parent);
|
||||
lv_obj_t* input_mix_group_create(lv_obj_t* parent);
|
||||
|
||||
@@ -608,6 +608,7 @@ const char STR_MODULE_PROTOCOL_WARN_LINE2[] = TR_MODULE_PROTOCOL_WARN_LINE2;
|
||||
const char STR_SET[] = TR_SET;
|
||||
const char STR_PREFLIGHT[] = TR_PREFLIGHT;
|
||||
const char STR_CHECKLIST[] = TR_CHECKLIST;
|
||||
const char STR_CHECKLIST_INTERACTIVE[] = TR_CHECKLIST_INTERACTIVE;
|
||||
const char STR_VIEW_NOTES[] = TR_VIEW_NOTES;
|
||||
const char STR_MODEL_SELECT[] = TR_MODEL_SELECT;
|
||||
const char STR_RESET_SUBMENU[] = TR_RESET_SUBMENU;
|
||||
|
||||
@@ -1001,6 +1001,7 @@ extern const char STR_SET[];
|
||||
extern const char* const STR_PREFLIGHT_POTSLIDER_CHECK[];
|
||||
extern const char STR_PREFLIGHT[];
|
||||
extern const char STR_CHECKLIST[];
|
||||
extern const char STR_CHECKLIST_INTERACTIVE[];
|
||||
extern const char STR_VIEW_NOTES[];
|
||||
extern const char STR_MODEL_SELECT[];
|
||||
extern const char STR_RESET_SUBMENU[];
|
||||
|
||||
@@ -900,6 +900,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "关闭","开启","自动"
|
||||
#define TR_PREFLIGHT "初始位置检查"
|
||||
#define TR_CHECKLIST TR(INDENT "显示列表", INDENT "显示列表")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "串口"
|
||||
#define TR_AUX2_SERIAL_MODE "串口 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "串口供电"
|
||||
|
||||
@@ -915,6 +915,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Vyp","Zap","Auto"
|
||||
#define TR_PREFLIGHT "Předletová kontrola"
|
||||
#define TR_CHECKLIST TR(INDENT "Poznámky", INDENT "Zobrazit poznámky")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Seriový port"
|
||||
#define TR_AUX2_SERIAL_MODE "Seriový port 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Výkon portu"
|
||||
|
||||
@@ -910,6 +910,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Fra","Til","Auto"
|
||||
#define TR_PREFLIGHT "Fly checkliste"
|
||||
#define TR_CHECKLIST TR(INDENT "Checkliste", INDENT "Vis checkliste")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Seriel port"
|
||||
#define TR_AUX2_SERIAL_MODE "Seriel port 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Port strøm"
|
||||
|
||||
@@ -903,6 +903,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Aus","Ein","Auto"
|
||||
#define TR_PREFLIGHT "Vorflug-Checkliste"
|
||||
#define TR_CHECKLIST TR(INDENT "Checkliste", INDENT "Checkliste anzeigen") //9XR-Pro
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Serieller Port"
|
||||
#define TR_AUX2_SERIAL_MODE "Serieller Port 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Versorgung"
|
||||
|
||||
@@ -904,6 +904,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "OFF","ON","AUTO"
|
||||
#define TR_PREFLIGHT "Preflight Checks"
|
||||
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Display checklist")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Serial port"
|
||||
#define TR_AUX2_SERIAL_MODE "Serial port 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Port power"
|
||||
|
||||
@@ -907,6 +907,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
|
||||
#define TR_PREFLIGHT "Chequeos prevuelo"
|
||||
#define TR_CHECKLIST TR(INDENT "Lista verif", INDENT "Lista verificación")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Puerto serie"
|
||||
#define TR_AUX2_SERIAL_MODE "Puerto serie 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Port power"
|
||||
|
||||
@@ -919,6 +919,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
|
||||
#define TR_PREFLIGHT "Preflight Checks"
|
||||
#define TR_CHECKLIST INDENT "Display Checklist"
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Sarjaportti"
|
||||
#define TR_AUX2_SERIAL_MODE "Sarjaportti 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Virta"
|
||||
|
||||
@@ -915,6 +915,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
|
||||
#define TR_PREFLIGHT "Vérifs avant vol"
|
||||
#define TR_CHECKLIST TR(INDENT "checklist", INDENT "Afficher checklist")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Port série"
|
||||
#define TR_AUX2_SERIAL_MODE "Port série 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Port power"
|
||||
|
||||
@@ -903,6 +903,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
|
||||
#define TR_PREFLIGHT "Controlli Prevolo"
|
||||
#define TR_CHECKLIST INDENT "Mostra Checklist"
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Porta Seriale"
|
||||
#define TR_AUX2_SERIAL_MODE "Porta Seriale 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Potenza porta AUX"
|
||||
|
||||
@@ -905,6 +905,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "OFF","ON","自動"
|
||||
#define TR_PREFLIGHT "飛行前チェック"
|
||||
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "チェックリスト表示")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "シリアルポート"
|
||||
#define TR_AUX2_SERIAL_MODE "シリアルポート 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "ポート出力"
|
||||
|
||||
@@ -906,6 +906,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Off","On","Auto"
|
||||
#define TR_PREFLIGHT "Preflight Checks"
|
||||
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Toon Checklist")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Seriele poort"
|
||||
#define TR_AUX2_SERIAL_MODE "Seriele poort 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Port power"
|
||||
|
||||
@@ -901,6 +901,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "WYŁ","ZAŁ","Auto"
|
||||
#define TR_PREFLIGHT "Lista Ostrzeżeń"
|
||||
#define TR_CHECKLIST TR(INDENT "Czeklista",INDENT "Pokaż Listę Ostrzeżeń")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR(INDENT "C-Interakt", INDENT "Interkatywna lista ostrż.")
|
||||
#define TR_AUX_SERIAL_MODE "Port szreg."
|
||||
#define TR_AUX2_SERIAL_MODE "Port szreg. 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Zasil.portu"
|
||||
|
||||
@@ -907,6 +907,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "DESL","LIGA","AUTO"
|
||||
#define TR_PREFLIGHT "Checagem PreVoo"
|
||||
#define TR_CHECKLIST TR(INDENT "Checklist", INDENT "Display checklist")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Serial port"
|
||||
#define TR_AUX2_SERIAL_MODE "Serial port 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Port power"
|
||||
|
||||
@@ -934,6 +934,7 @@
|
||||
#define TR_PREFLIGHT "Startkontroller"
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "Av","På","Auto"
|
||||
#define TR_CHECKLIST TR(INDENT "Checklista", INDENT "Visa checklista")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR(INDENT "C-Interact", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "Serieport"
|
||||
#define TR_AUX2_SERIAL_MODE "Serieport 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "Strömkälla"
|
||||
|
||||
@@ -904,6 +904,7 @@
|
||||
#define TR_PREFLIGHT_POTSLIDER_CHECK "關閉","開啟","自動"
|
||||
#define TR_PREFLIGHT "初始位置檢查"
|
||||
#define TR_CHECKLIST TR(INDENT "顯示列表", INDENT "顯示列表")
|
||||
#define TR_CHECKLIST_INTERACTIVE TR3(INDENT "C-Interact", INDENT "Interact. checklist", INDENT "Interactive checklist")
|
||||
#define TR_AUX_SERIAL_MODE "端口"
|
||||
#define TR_AUX2_SERIAL_MODE "端口 2"
|
||||
#define TR_AUX_SERIAL_PORT_POWER "端口供電"
|
||||
|
||||
Reference in New Issue
Block a user