//====================================================================== // menu.h //====================================================================== #ifndef __menu_h__ #define __menu_h__ //#include "etl_profile.h" //#include #include "etl/array.h" #include "etl/cstring.h" #include "etl/delegate.h" //#include #include #include "rig.h" // 16 characters on display const int MAX_TEXT_LEN = 16; const int max_text_len = 16; const char MENU_SELECTED_CHAR = '>'; const char menu_selection_char = '>'; const char blankLine[17] = " "; typedef etl::string Menu_string; //====================================================================== // Menu_item //====================================================================== class Menu_item { public: Menu_item(): parent_link(nullptr) {} virtual ~Menu_item() {} virtual const Menu_string& title() const = 0; virtual void get_title(Menu_string& outstr) const = 0; virtual void get_text(Menu_string& outstr) const = 0; virtual Menu_item* select() = 0; virtual Menu_item* altSelect() = 0; virtual Menu_item* exit() = 0; virtual Menu_item* prev() = 0; virtual Menu_item* next() = 0; void set_parent(Menu_item* item) { parent_link = item; } const Menu_item* parent() const { return parent_link; } private: Menu_item* parent_link; }; //====================================================================== // List_menu //====================================================================== const int MAX_LISTMENU_TITLE_LEN = 15; //const int max_size_of_list_menu = 20; // arbitrary... template class List_menu : public Menu_item { public: List_menu(const char* title, etl::array items): Menu_item(), list_title(title), list_items(items), index(0) { for (auto element : list_items) { element->set_parent(this); } } virtual const Menu_string& title() const { return list_title; } virtual void get_title(Menu_string& outstr) const { outstr.assign(list_title); } virtual void get_text(Menu_string& outstr) const { list_items[index]->get_text(outstr); } virtual Menu_item* select() { return list_items[index]; } virtual Menu_item* altSelect() { return this; } virtual Menu_item* exit() { return parent(); } virtual Menu_item* prev() { if (--index < 0) { index += list_items.size(); } return this; } virtual Menu_item* next() { index = ++index % list_items.size(); return this; } private: Menu_string list_title; etl::array list_items; int index; }; //====================================================================== // Config_parm //====================================================================== typedef etl::delegate Update_func; template class Config_parm : public Menu_item { public: Config_parm(const char* title, T& parm, T min, T max, T step, Update_func f): Menu_item(), parm_title(title), parameter(parm), min_val(min), max_val(max), step_val(step), on_update(f) {} virtual const Menu_string& title() const { return parm_title; } virtual void get_title(Menu_string& outstr) const { outstr.assign(parm_title); } virtual void get_text(Menu_string& outstr) const = 0; virtual Menu_item* select() { on_update(); return parent(); } virtual Menu_item* altSelect() { on_update(); return this; } virtual Menu_item* exit() { return parent(); } virtual Menu_item* prev() { parameter -= step_val; if (parameter < min_val) { parameter = min_val; } return this; } virtual Menu_item* next() { parameter += step_val; if (parameter > max_val) { parameter = max_val; } return this; } const T& value() const { return parameter; } private: Menu_string parm_title; T& parameter; T min_val; T max_val; T step_val; Update_func on_update; }; class Parm_uint8 : public Config_parm { public: Parm_uint8(const char* title, uint8_t& parm, uint8_t min, uint8_t max, uint8_t step, Update_func f): Config_parm(title, parm, min, max, step, f) {} virtual void get_text(Menu_string& outstr) const { snprintf(outstr.data(), max_text_len+1, "%-*.*s %3d", max_text_len-4, max_text_len-4, title().data(), value()); } }; class Parm_float : public Config_parm { public: Parm_float(const char* title, float& parm, float min, float max, float step, Update_func f): Config_parm(title, parm, min, max, step, f) {} virtual void get_text(Menu_string& outstr) const { snprintf(outstr.data(), max_text_len+1, "%-*.*s %5.2f", max_text_len-6, max_text_len-6, title().data(), value()); } }; //====================================================================== const char modeID[] = {'s', 'S', 'c', 'C', 'd', 'D', 't', 'T'}; const char* const filterID[static_cast(rig_mode::count)][static_cast(rx_filter::count)] = { {"2.8", "2.4", "1.8"}, // SSB {"1.0", "500", "250"}, // CW {"2.8", "2.4", "500"}, // DIG }; //====================================================================== // Top_menu //====================================================================== class Main_menu : public Menu_item { public: Main_menu(basic_rig& rig): menu_title("Main Menu"), rig_(rig), adjust_tx(false) {} virtual const Menu_string& title() const { return menu_title; } virtual void get_title(Menu_string& outstr) const { outstr.assign(menu_title); } virtual void get_text(Menu_string& outstr) const { char text[max_text_len+1]; sprintf(text, "%1cR:%3s %1cT:%3s ", adjust_tx ? ' ' : menu_selection_char, filterID[static_cast(rig_.get_rig_mode())][static_cast(rig_.get_rx_filter())], adjust_tx ? menu_selection_char : ' ', rig_.is_ssb_mode() && rig_.config().ssb.comp.enabled ? "CMP" : " "); outstr.assign(text); } virtual Menu_item* select() { adjust_tx = !adjust_tx; return this; } virtual Menu_item* altSelect() { return this; } virtual Menu_item* exit() { return nullptr; } virtual Menu_item* prev() { if (adjust_tx) { if (rig_.is_ssb_mode()) { rig_.config().ssb.comp.enabled = !rig_.config().ssb.comp.enabled; if (rig_.config().ssb.comp.enabled) rig_.enable_comp(); else rig_.disable_comp(); } } else { rig_.prev_rx_filter(); } return this; } virtual Menu_item* next() { if (adjust_tx) { if (rig_.is_ssb_mode()) { rig_.config().ssb.comp.enabled = !rig_.config().ssb.comp.enabled; if (rig_.config().ssb.comp.enabled) rig_.enable_comp(); else rig_.disable_comp(); } } else { rig_.next_rx_filter(); } return this; } private: Menu_string menu_title; basic_rig& rig_; bool adjust_tx; }; extern const Menu_item* audio_config_menu; #endif //====================================================================== // EOF //======================================================================