diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index 1da4e3520fd..5ca2d5a5de4 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -920,6 +920,7 @@ Node convert::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::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; diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 09e1b000aef..806f1c1d3ac 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -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]; diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index f7b081b2f8d..fe1576c427c 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -1795,6 +1795,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); @@ -1942,6 +1943,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; diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index af83bce3797..841e23f45a6 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -190,6 +190,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); diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui index 010ce675806..9ff59393630 100644 --- a/companion/src/modeledit/setup.ui +++ b/companion/src/modeledit/setup.ui @@ -579,6 +579,16 @@ + + + + Qt::LeftToRight + + + Interactive Checklist + + + diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 727974e9202..325b2af76f5 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -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; diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index e31d2dbc73e..4bf0d7b2b64 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -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); diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 5d86a23f8c4..457c35797c8 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -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); diff --git a/radio/src/gui/colorlcd/preflight_checks.cpp b/radio/src/gui/colorlcd/preflight_checks.cpp index 781067687bc..12b946f7533 100644 --- a/radio/src/gui/colorlcd/preflight_checks.cpp +++ b/radio/src/gui/colorlcd/preflight_checks.cpp @@ -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); diff --git a/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp b/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp index af6484701df..c47ace5a4a5 100644 --- a/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp +++ b/radio/src/gui/colorlcd/themes/etx_lv_theme.cpp @@ -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); diff --git a/radio/src/gui/colorlcd/view_main_menu.cpp b/radio/src/gui/colorlcd/view_main_menu.cpp index d5efe112b5e..d36fda303f1 100644 --- a/radio/src/gui/colorlcd/view_main_menu.cpp +++ b/radio/src/gui/colorlcd/view_main_menu.cpp @@ -55,7 +55,7 @@ ViewMainMenu::ViewMainMenu(Window* parent, std::function closeHandler) : if (modelHasNotes()) { carousel->addButton(ICON_MODEL_NOTES, STR_MAIN_MENU_MODEL_NOTES, [=]() -> uint8_t { deleteLater(); - readModelNotes(); + readModelNotes(true); return 0; }); } diff --git a/radio/src/gui/colorlcd/view_text.cpp b/radio/src/gui/colorlcd/view_text.cpp index acf47397d58..30a38428aa9 100644 --- a/radio/src/gui/colorlcd/view_text.cpp +++ b/radio/src/gui/colorlcd/view_text.cpp @@ -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 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= 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