From 4b8628524b9ec4426632e51ec7549949b2b4a6b5 Mon Sep 17 00:00:00 2001 From: philmoz Date: Sun, 24 Nov 2024 10:03:45 +1100 Subject: [PATCH] fix(color): cannot change 'Invert' state on radios with no touch screen (#5663) in switch and source choice popup --- .../gui/colorlcd/controls/sourcechoice.cpp | 9 +-- .../gui/colorlcd/controls/switchchoice.cpp | 8 +-- radio/src/gui/colorlcd/libui/file_browser.cpp | 43 ++--------- radio/src/gui/colorlcd/libui/file_browser.h | 2 - radio/src/gui/colorlcd/libui/listbox.cpp | 71 +------------------ radio/src/gui/colorlcd/libui/listbox.h | 11 --- radio/src/gui/colorlcd/libui/menu.cpp | 35 ++++----- radio/src/gui/colorlcd/libui/menu.h | 4 ++ radio/src/gui/colorlcd/libui/table.cpp | 49 ++++++++++--- radio/src/gui/colorlcd/libui/table.h | 16 ++++- radio/src/gui/colorlcd/radio/radio_theme.cpp | 2 +- 11 files changed, 93 insertions(+), 157 deletions(-) diff --git a/radio/src/gui/colorlcd/controls/sourcechoice.cpp b/radio/src/gui/colorlcd/controls/sourcechoice.cpp index 0ac19cc96..962cb1088 100644 --- a/radio/src/gui/colorlcd/controls/sourcechoice.cpp +++ b/radio/src/gui/colorlcd/controls/sourcechoice.cpp @@ -104,7 +104,6 @@ class SourceChoiceMenuToolbar : public MenuToolbar choice->isValueAvailable(0)) addButton(STR_SELECT_MENU_CLR, 0, 0, nullptr, nullptr, true); -#if defined(HARDWARE_TOUCH) if (choice->canInvert) { invertBtn = new MenuToolbarButton(this, {0, 0, LV_PCT(100), 0}, STR_SELECT_MENU_INV); @@ -117,7 +116,6 @@ class SourceChoiceMenuToolbar : public MenuToolbar return choice->inverted; }); } -#endif } void invertChoice() @@ -128,9 +126,7 @@ class SourceChoiceMenuToolbar : public MenuToolbar auto idx = menu->selection(); sourceChoice->fillMenu(menu, filter); menu->select(idx); -#if defined(HARDWARE_TOUCH) invertBtn->check(sourceChoice->inverted); -#endif } } @@ -145,9 +141,7 @@ class SourceChoiceMenuToolbar : public MenuToolbar static LAYOUT_VAL(FILTER_COLUMNS, 3, 2) protected: -#if defined(HARDWARE_TOUCH) MenuToolbarButton* invertBtn = nullptr; -#endif }; bool SourceChoice::onLongPress() @@ -192,6 +186,9 @@ void SourceChoice::openMenu() auto tb = new SourceChoiceMenuToolbar(this, menu); menu->setToolbar(tb); + if (canInvert) + menu->setLongPressHandler([=]() { tb->invertChoice(); }); + #if defined(AUTOSOURCE) menu->setWaitHandler([=]() { int16_t val = getMovedSource(vmin); diff --git a/radio/src/gui/colorlcd/controls/switchchoice.cpp b/radio/src/gui/colorlcd/controls/switchchoice.cpp index c7c305134..33372fd03 100644 --- a/radio/src/gui/colorlcd/controls/switchchoice.cpp +++ b/radio/src/gui/colorlcd/controls/switchchoice.cpp @@ -63,7 +63,6 @@ class SwitchChoiceMenuToolbar : public MenuToolbar choice->isValueAvailable(0)) addButton(STR_SELECT_MENU_CLR, 0, 0, nullptr, nullptr, true); -#if defined(HARDWARE_TOUCH) invertBtn = new MenuToolbarButton(this, {0, 0, LV_PCT(100), 0}, STR_SELECT_MENU_INV); invertBtn->check(choice->inverted); @@ -74,7 +73,6 @@ class SwitchChoiceMenuToolbar : public MenuToolbar invertChoice(); return choice->inverted; }); -#endif } void invertChoice() @@ -84,9 +82,7 @@ class SwitchChoiceMenuToolbar : public MenuToolbar auto idx = menu->selection(); switchChoice->fillMenu(menu, filter); menu->select(idx); -#if defined(HARDWARE_TOUCH) invertBtn->check(switchChoice->inverted); -#endif } void longPress() @@ -98,9 +94,7 @@ class SwitchChoiceMenuToolbar : public MenuToolbar } protected: -#if defined(HARDWARE_TOUCH) MenuToolbarButton* invertBtn = nullptr; -#endif }; bool SwitchChoice::onLongPress() @@ -140,6 +134,8 @@ void SwitchChoice::openMenu() auto tb = new SwitchChoiceMenuToolbar(this, menu); menu->setToolbar(tb); + menu->setLongPressHandler([=]() { tb->invertChoice(); }); + #if defined(AUTOSWITCH) menu->setWaitHandler([=]() { swsrc_t val = 0; diff --git a/radio/src/gui/colorlcd/libui/file_browser.cpp b/radio/src/gui/colorlcd/libui/file_browser.cpp index 4a3f5250f..394b65582 100644 --- a/radio/src/gui/colorlcd/libui/file_browser.cpp +++ b/radio/src/gui/colorlcd/libui/file_browser.cpp @@ -29,29 +29,6 @@ #define CELL_CTRL_DIR LV_TABLE_CELL_CTRL_CUSTOM_1 #define CELL_CTRL_FILE LV_TABLE_CELL_CTRL_CUSTOM_2 -static void fb_event(lv_event_t* e) -{ - static bool nested = false; - if (nested) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t* obj = lv_event_get_target(e); - if (!obj) return; - - lv_group_t* g = (lv_group_t*)lv_obj_get_group(obj); - if (!g) return; - - if (code == LV_EVENT_FOCUSED) { - lv_group_set_editing(g, true); - } else if (code == LV_EVENT_DEFOCUSED) { - // hack to get rid 'FOCUSED' event sent - // when calling 'lv_group_set_editing' - nested = true; - lv_group_set_editing(g, false); - nested = false; - } -} - static const char* getFullPath(const char* filename) { static char full_path[FF_MAX_LFN + 1]; @@ -164,14 +141,15 @@ static int scan_files(std::list& files, FileBrowser::FileBrowser(Window* parent, const rect_t& rect, const char* dir) : TableField(parent, rect) { - lv_obj_add_event_cb(lvobj, fb_event, LV_EVENT_ALL, nullptr); - f_chdir(dir); - if (lv_obj_has_state(lvobj, LV_STATE_FOCUSED)) { - lv_group_t* g = (lv_group_t*)lv_obj_get_group(lvobj); - if (g) lv_group_set_editing(g, true); - } + setAutoEdit(); + + setLongPressHandler([=]() { + int row = getSelected(); + bool is_dir = lv_table_has_cell_ctrl(lvobj, row, 0, CELL_CTRL_DIR); + onPressLong(lv_table_get_cell_value(lvobj, row, 0), is_dir); + }); } void FileBrowser::setFileAction(FileAction fct) { fileAction = std::move(fct); } @@ -222,13 +200,6 @@ void FileBrowser::onPress(uint16_t row, uint16_t col) onPress(lv_table_get_cell_value(lvobj, row, col), is_dir); } -bool FileBrowser::onPressLong(uint16_t row, uint16_t col) -{ - bool is_dir = lv_table_has_cell_ctrl(lvobj, row, col, CELL_CTRL_DIR); - onPressLong(lv_table_get_cell_value(lvobj, row, col), is_dir); - return true; -} - void FileBrowser::onDrawBegin(uint16_t row, uint16_t col, lv_obj_draw_part_dsc_t* dsc) { lv_coord_t cell_left = lv_obj_get_style_pad_left(lvobj, LV_PART_ITEMS); diff --git a/radio/src/gui/colorlcd/libui/file_browser.h b/radio/src/gui/colorlcd/libui/file_browser.h index 605096d8b..e968a5f9f 100644 --- a/radio/src/gui/colorlcd/libui/file_browser.h +++ b/radio/src/gui/colorlcd/libui/file_browser.h @@ -45,8 +45,6 @@ class FileBrowser : public TableField // TableField methods void onSelected(uint16_t row, uint16_t col) override; void onPress(uint16_t row, uint16_t col) override; - bool onPressLong(uint16_t row, uint16_t col) override; - bool onLongPress() override { return false; } protected: void onSelected(const char* name, bool is_dir); diff --git a/radio/src/gui/colorlcd/libui/listbox.cpp b/radio/src/gui/colorlcd/libui/listbox.cpp index 1f49e2421..2980a94bb 100644 --- a/radio/src/gui/colorlcd/libui/listbox.cpp +++ b/radio/src/gui/colorlcd/libui/listbox.cpp @@ -20,55 +20,18 @@ */ #include "listbox.h" - #include "libopenui.h" -void ListBox::event_cb(lv_event_t* e) -{ - static bool _nested = false; - if (_nested) return; - - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t* obj = lv_event_get_target(e); - if (!obj) return; - - ListBox* lb = (ListBox*)lv_event_get_user_data(e); - if (!lb) return; - - if (code == LV_EVENT_FOCUSED && lb->autoEdit) { - lv_group_set_editing((lv_group_t*)lv_obj_get_group(obj), true); - } else if (code == LV_EVENT_DEFOCUSED) { - // Hack to get rid of 'FOCUSED' event sent - // when calling 'lv_group_set_editing()' - _nested = true; - lv_group_set_editing((lv_group_t*)lv_obj_get_group(obj), false); - _nested = false; - } -} - ListBox::ListBox(Window* parent, const rect_t& rect, const std::vector& names, uint8_t lineHeight) : TableField(parent, rect) { - lv_obj_add_event_cb(lvobj, ListBox::event_cb, LV_EVENT_ALL, this); - setColumnWidth(0, rect.w); setLineHeight(lineHeight); setNames(names); } -void ListBox::setAutoEdit(bool enable) -{ - if (autoEdit == enable) return; - - autoEdit = enable; - if (autoEdit && hasFocus()) { - lv_group_t* g = (lv_group_t*)lv_obj_get_group(lvobj); - if (g) lv_group_set_editing(g, true); - } -} - void ListBox::setName(uint16_t idx, const std::string& name) { lv_table_set_cell_value(lvobj, idx, 0, name.c_str()); @@ -107,16 +70,6 @@ void ListBox::setSelected(std::set selected) } } -int ListBox::getSelected() const -{ - uint16_t row, col; - lv_table_get_selected_cell(lvobj, &row, &col); - if (row != LV_TABLE_CELL_NONE) { - return row; - } - return -1; -} - bool ListBox::isRowSelected(uint16_t row) { return lv_table_has_cell_ctrl(lvobj, row, 0, LV_TABLE_CELL_CTRL_CUSTOM_1); @@ -168,33 +121,15 @@ void ListBox::onPress(uint16_t row, uint16_t col) } } -bool ListBox::onLongPress() -{ - TRACE("LONG_PRESS"); - if (longPressHandler) { - longPressHandler(); - lv_indev_wait_release(lv_indev_get_act()); - return false; - } - return true; -} - -// TODO: !auto-edit void ListBox::onClicked() { - if (!autoEdit) { - lv_group_set_editing((lv_group_t*)lv_obj_get_group(lvobj), true); - - } else { - TableField::onClicked(); - } + lv_group_set_editing((lv_group_t*)lv_obj_get_group(lvobj), true); } void ListBox::onCancel() { - lv_group_t* g = (lv_group_t*)lv_obj_get_group(lvobj); - if (!autoEdit && lv_group_get_editing(g)) { - lv_group_set_editing(g, false); + if (!isAutoEdit() && lv_group_get_editing((lv_group_t*)lv_obj_get_group(lvobj))) { + lv_group_set_editing((lv_group_t*)lv_obj_get_group(lvobj), false); } else { TableField::onCancel(); } diff --git a/radio/src/gui/colorlcd/libui/listbox.h b/radio/src/gui/colorlcd/libui/listbox.h index d7aff78db..e54d62e0b 100644 --- a/radio/src/gui/colorlcd/libui/listbox.h +++ b/radio/src/gui/colorlcd/libui/listbox.h @@ -29,20 +29,16 @@ // Class for lists of elements with names class ListBox : public TableField { - std::function longPressHandler = nullptr; std::function pressHandler = nullptr; std::function, std::set)> _multiSelectHandler = nullptr; std::function getSelectedSymbol = nullptr; - bool autoEdit = false; public: ListBox(Window* parent, const rect_t& rect, const std::vector& names, uint8_t lineHeight = MENUS_LINE_HEIGHT); - void setAutoEdit(bool enable); - void setName(uint16_t idx, const std::string& name); void setNames(const std::vector& names); void setLineHeight(uint8_t height); @@ -50,7 +46,6 @@ class ListBox : public TableField virtual void setSelected(int selected, bool force = false); virtual void setSelected(std::set selected); - int getSelected() const; bool isRowSelected(uint16_t row); std::set getSelection(); @@ -70,11 +65,6 @@ class ListBox : public TableField getSelectedSymbol = std::move(handler); } - void setLongPressHandler(std::function handler) - { - longPressHandler = std::move(handler); - } - void setPressHandler(std::function handler) { pressHandler = std::move(handler); @@ -95,7 +85,6 @@ class ListBox : public TableField bool smallSelectMarker = false; void onPress(uint16_t row, uint16_t col) override; - bool onLongPress() override; void onClicked() override; void onCancel() override; diff --git a/radio/src/gui/colorlcd/libui/menu.cpp b/radio/src/gui/colorlcd/libui/menu.cpp index de5cc14dd..cad3fc11e 100644 --- a/radio/src/gui/colorlcd/libui/menu.cpp +++ b/radio/src/gui/colorlcd/libui/menu.cpp @@ -25,9 +25,7 @@ #include "table.h" #include "etx_lv_theme.h" -constexpr coord_t MENUS_WIDTH = 200; - -static void _force_editing(lv_group_t* g) { lv_group_set_editing(g, true); } +//----------------------------------------------------------------------------- class MenuBody : public TableField { @@ -76,17 +74,11 @@ class MenuBody : public TableField setColumnWidth(0, rect.w); - lv_group_t* g = (lv_group_t*)lv_obj_get_group(lvobj); - if (g) { - setFocusHandler([=](bool focus) { - if (focus) { - lv_group_set_focus_cb(g, _force_editing); - } else { - lv_group_set_focus_cb(g, nullptr); - } - }); - lv_group_set_editing(g, true); - } + setAutoEdit(); + + setLongPressHandler([=]() { + getParentMenu()->handleLongPress(); + }); } ~MenuBody() @@ -276,8 +268,6 @@ class MenuBody : public TableField void onSelected(uint16_t row, uint16_t col) override { selectedIndex = row; } protected: - bool isLongPressed = false; - std::vector lines; int selectedIndex = 0; @@ -357,6 +347,8 @@ class MenuWindowContent : public Window body->addLine(icon_mask, text, onPress, isChecked, update); } + static constexpr coord_t MENUS_WIDTH = 200; + protected: StaticText* header = nullptr; MenuBody* body = nullptr; @@ -453,6 +445,17 @@ void Menu::setWaitHandler(std::function handler) waitHandler = std::move(handler); } +void Menu::setLongPressHandler(std::function handler) +{ + longPressHandler = std::move(handler); +} + +void Menu::handleLongPress() +{ + if (longPressHandler) + longPressHandler(); +} + unsigned Menu::count() const { return content->count(); } int Menu::selection() const { return content->selection(); } diff --git a/radio/src/gui/colorlcd/libui/menu.h b/radio/src/gui/colorlcd/libui/menu.h index 6ebdefe14..4b465af90 100644 --- a/radio/src/gui/colorlcd/libui/menu.h +++ b/radio/src/gui/colorlcd/libui/menu.h @@ -37,6 +37,7 @@ class Menu : public ModalWindow void setCancelHandler(std::function handler); void setWaitHandler(std::function handler); + void setLongPressHandler(std::function handler); void setToolbar(MenuToolbar *window); @@ -83,12 +84,15 @@ class Menu : public ModalWindow } } + void handleLongPress(); + protected: bool multiple; MenuWindowContent *content; MenuToolbar *toolbar = nullptr; std::function waitHandler; std::function cancelHandler; + std::function longPressHandler; void updatePosition(); }; diff --git a/radio/src/gui/colorlcd/libui/table.cpp b/radio/src/gui/colorlcd/libui/table.cpp index bce2c821c..e4884ee98 100644 --- a/radio/src/gui/colorlcd/libui/table.cpp +++ b/radio/src/gui/colorlcd/libui/table.cpp @@ -40,6 +40,7 @@ static void table_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) etx_txt_color(obj, COLOR_THEME_PRIMARY1_INDEX, LV_PART_ITEMS); etx_obj_add_style(obj, table_cell, LV_PART_ITEMS); etx_obj_add_style(obj, styles->border_color[COLOR_THEME_SECONDARY2_INDEX], LV_PART_ITEMS); + etx_obj_add_style(obj, styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED); etx_bg_color(obj, COLOR_THEME_FOCUS_INDEX, LV_PART_ITEMS | LV_STATE_EDITED); etx_txt_color(obj, COLOR_THEME_PRIMARY2_INDEX, LV_PART_ITEMS | LV_STATE_EDITED); @@ -85,13 +86,7 @@ void TableField::table_event(const lv_obj_class_t* class_p, lv_event_t* e) // Otherwise it's a click if (lv_group_get_editing((lv_group_t*)lv_obj_get_group(obj)) || indev_type == LV_INDEV_TYPE_POINTER) { - if (tf->isLongPress) { - tf->isLongPress = false; - if (!tf->onPressLong(row, col)) - tf->onPress(row, col); - } else { - tf->onPress(row, col); - } + tf->onPress(row, col); } else { tf->onClicked(); } @@ -152,9 +147,6 @@ void TableField::table_event(const lv_obj_class_t* class_p, lv_event_t* e) lv_draw_rect(draw_ctx, &rect_dsc, &coords); } } break; - case LV_EVENT_LONG_PRESSED: - tf->isLongPress = true; - break; case LV_EVENT_RELEASED: { lv_table_t* table = (lv_table_t*)obj; @@ -291,3 +283,40 @@ void TableField::onEvent(event_t event) Window::onEvent(event); } } + +int TableField::getSelected() const +{ + uint16_t row, col; + lv_table_get_selected_cell(lvobj, &row, &col); + if (row != LV_TABLE_CELL_NONE) { + return row; + } + return -1; +} + +bool TableField::onLongPress() +{ + TRACE("LONG_PRESS"); + if (longPressHandler) { + longPressHandler(); + lv_indev_wait_release(lv_indev_get_act()); + return false; + } + return true; +} + +void TableField::setAutoEdit() +{ + autoedit = true; + lv_group_t* g = (lv_group_t*)lv_obj_get_group(lvobj); + if (g) { + setFocusHandler([=](bool focus) { + if (focus) { + lv_group_set_focus_cb(g, TableField::force_editing); + } else { + lv_group_set_focus_cb(g, nullptr); + } + }); + lv_group_set_editing(g, true); + } +} diff --git a/radio/src/gui/colorlcd/libui/table.h b/radio/src/gui/colorlcd/libui/table.h index e4900d1f7..d088e0618 100644 --- a/radio/src/gui/colorlcd/libui/table.h +++ b/radio/src/gui/colorlcd/libui/table.h @@ -45,10 +45,24 @@ class TableField : public Window void adjustScroll(); void selectNext(int16_t dir); + void setAutoEdit(); + bool isAutoEdit() const { return autoedit; } + + int getSelected() const; + + void setLongPressHandler(std::function handler) + { + longPressHandler = std::move(handler); + } + static void table_event(const lv_obj_class_t* class_p, lv_event_t* e); protected: - bool isLongPress = false; + bool autoedit = false; + std::function longPressHandler = nullptr; void onEvent(event_t event) override; + bool onLongPress() override; + + static void force_editing(lv_group_t* g) { lv_group_set_editing(g, true); } }; diff --git a/radio/src/gui/colorlcd/radio/radio_theme.cpp b/radio/src/gui/colorlcd/radio/radio_theme.cpp index 82ee7bf4d..4b8b01cfc 100644 --- a/radio/src/gui/colorlcd/radio/radio_theme.cpp +++ b/radio/src/gui/colorlcd/radio/radio_theme.cpp @@ -595,7 +595,7 @@ void ThemeSetupPage::setupListbox(Window *window, rect_t r, { listBox = new ListBox(window, r, tp->getNames()); etx_scrollbar(listBox->getLvObj()); - listBox->setAutoEdit(true); + listBox->setAutoEdit(); listBox->setSelected(currentTheme); listBox->setActiveItem(tp->getThemeIndex()); listBox->setLongPressHandler([=]() {