diff --git a/ExternalApps/RadioSet/main/CMakeLists.txt b/ExternalApps/RadioSet/main/CMakeLists.txt index 62c36897..9ae526fe 100644 --- a/ExternalApps/RadioSet/main/CMakeLists.txt +++ b/ExternalApps/RadioSet/main/CMakeLists.txt @@ -4,3 +4,5 @@ idf_component_register( SRCS ${SOURCE_FILES} REQUIRES TactilitySDK ) + +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=uninitialized -Wno-error=maybe-uninitialized) diff --git a/ExternalApps/RadioSet/main/Source/RadioSet.cpp b/ExternalApps/RadioSet/main/Source/RadioSet.cpp index 2245fd0a..7d096497 100644 --- a/ExternalApps/RadioSet/main/Source/RadioSet.cpp +++ b/ExternalApps/RadioSet/main/Source/RadioSet.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include "tt_app_alertdialog.h" constexpr const char* TAG = "RadioSet"; @@ -13,21 +15,378 @@ void crash(const char* const message) { tt_app_alertdialog_start("RadioSet has crashed!", message, nullptr, 0); } +// Debug function which colors all children randomly +// TODO: Remove before flight +void clownvomit(lv_obj_t *obj) { + static auto rng = []() { + static int color = 0xC0FE; + const int a = 4711; + const int m = 0x10001; + color = (a * color) % m; + return color; + }; + + const int darken = 0x0E0E0E; + const int lighten = 0xFEFEFE; + lv_obj_set_style_bg_color(obj, lv_color_hex(rng() & darken), 0); + + uint32_t i; + for(i = 0; i < lv_obj_get_child_count(obj); i++) { + lv_obj_t * child = lv_obj_get_child(obj, i); + lv_obj_set_style_bg_color(child, lv_color_hex(rng() & darken), 0); + lv_obj_set_style_border_color(child, lv_color_hex(rng() | lighten), 0); + lv_obj_set_style_border_width(child, 1, 0); + clownvomit(child); + } +} +/* +void scrollbar_highlight(lv_event_t * e) { + lv_obj_t * obj = lv_event_get_target(e); +}*/ + +char *const toString(Modulation m) { + switch (m) { + case MODULATION_NONE: + return "None"; + case MODULATION_LORA: + return "LoRa"; + case MODULATION_FSK: + return "FSK"; + case MODULATION_LRFHSS: + return "LR-FHSS"; + default: + break; + } + crash("Unknown modulation passed."); + return "Unknown"; +} + +char *const toString(RadioParameter p) { + switch (p) { + case RADIO_POWER: + return "Power"; + case RADIO_FREQUENCY: + return "Center Frequency"; + case RADIO_BANDWIDTH: + return "Bandwidth"; + case RADIO_SPREADFACTOR: + return "Spread Factor"; + case RADIO_CODINGRATE: + return "Coding Rate"; + case RADIO_SYNCWORD: + return "Sync Word"; + case RADIO_PREAMBLES: + return "Preamble Length"; + case RADIO_FREQDIV: + return "Frequency Deviation"; + case RADIO_DATARATE: + return "Data Rate"; + case RADIO_ADDRWIDTH: + return "Address Width"; + case RADIO_NARROWGRID: + return "Narrow Grid"; + default: + break; + } + crash("Unknown parameter passed."); + return "Unknown"; +} + class TermView { }; + +static lv_obj_t* initGridDropdownInput(lv_obj_t *container, int row, const char* const label, const char* const items) { + lv_obj_t* label_obj = lv_label_create(container); + lv_label_set_text(label_obj, label); + lv_obj_set_grid_cell(label_obj, + LV_GRID_ALIGN_STRETCH, 0, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(label_obj, lv_pct(100), LV_SIZE_CONTENT); + + lv_obj_t* input = lv_dropdown_create(container); + lv_obj_set_grid_cell(input, + LV_GRID_ALIGN_STRETCH, 1, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(input, lv_pct(100), LV_SIZE_CONTENT); + lv_dropdown_set_options(input, items); + + return input; +} + +static lv_obj_t* initGridTextInput(lv_obj_t *container, int row, const char* const label, const char* const defval, const char* const unit) { + const int height = LV_SIZE_CONTENT; + lv_obj_t* label_obj = lv_label_create(container); + lv_label_set_text(label_obj, label); + lv_obj_set_grid_cell(label_obj, + LV_GRID_ALIGN_STRETCH, 0, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(label_obj, lv_pct(100), height); + + lv_obj_t* input = lv_textarea_create(container); + lv_obj_set_grid_cell(input, + LV_GRID_ALIGN_STRETCH, 1, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(input, lv_pct(100), height); + lv_textarea_set_text(input, defval); + lv_textarea_set_one_line(input, true); + + lv_obj_t* unit_obj = lv_label_create(container); + lv_label_set_text(unit_obj, unit); + lv_obj_set_grid_cell(unit_obj, + LV_GRID_ALIGN_STRETCH, 2, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(unit_obj, lv_pct(100), height); + lv_obj_set_style_text_align(unit_obj , LV_TEXT_ALIGN_CENTER, 0); + + return input; +} + +struct ParameterInput { + const RadioHandle handle; + const RadioParameter param; + + ParameterInput(RadioHandle handle, const RadioParameter param) + : handle(handle) + , param(param) {} + virtual void updatePreview() = 0; +}; + +struct NumericParameterInput : public ParameterInput { + + lv_obj_t* label = nullptr; + lv_obj_t* input = nullptr; + lv_obj_t* unitlabel = nullptr; + char* fmt; + + NumericParameterInput(RadioHandle handle, const RadioParameter param, lv_obj_t* container, int row, char* fmt = "%f", char* unit_override = nullptr) + : ParameterInput(handle, param) + , fmt(fmt) { + initUi(container, row, unit_override); + loadFromRadio(); + } + + void loadFromRadio() { + + } + + void initUi(lv_obj_t* container, int row, char* unit_override) { + const int height = LV_SIZE_CONTENT; + label = lv_label_create(container); + lv_label_set_text(label, toString(param)); + lv_obj_set_grid_cell(label, + LV_GRID_ALIGN_STRETCH, 0, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(label, lv_pct(100), height); + + input = lv_textarea_create(container); + lv_obj_set_grid_cell(input, + LV_GRID_ALIGN_STRETCH, 1, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(input, lv_pct(100), height); + //TODO: LOAD VALUE + //lv_textarea_set_text(input, defval); + lv_textarea_set_one_line(input, true); + + unitlabel = lv_label_create(container); + lv_obj_set_grid_cell(unitlabel, + LV_GRID_ALIGN_STRETCH, 2, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(unitlabel, lv_pct(100), height); + lv_obj_set_style_text_align(unitlabel , LV_TEXT_ALIGN_CENTER, 0); + + if (unit_override) { + lv_label_set_text(unitlabel, unit_override); + } else { + char unit[64] = {0}; + tt_hal_radio_get_parameter_unit_str(handle, param, unit, sizeof(unit)); + lv_label_set_text(unitlabel, unit); + } + } + + virtual void updatePreview() override {} +}; + +struct SliderParameterInput : public ParameterInput { + char* fmt = nullptr; + lv_obj_t* label = nullptr; + lv_obj_t* slider = nullptr; + lv_obj_t* preview = nullptr; + + SliderParameterInput(RadioHandle handle, const RadioParameter param, lv_obj_t* container, int row, int min, int max, char* fmt = "%i") + : ParameterInput(handle, param) + , fmt(fmt) { + initUi(container, row, min, max); + } + + void initUi(lv_obj_t* container, int row, int min, int max) { + label = lv_label_create(container); + lv_label_set_text(label, toString(param)); + lv_obj_set_grid_cell(label, + LV_GRID_ALIGN_STRETCH, 0, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(label, lv_pct(100), LV_SIZE_CONTENT); + + slider = lv_slider_create(container); + lv_obj_set_grid_cell(slider, + LV_GRID_ALIGN_STRETCH, 1, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(slider, lv_pct(100), 10); + lv_slider_set_range(slider, min, max); + + preview = lv_label_create(container); + lv_obj_set_grid_cell(preview, + LV_GRID_ALIGN_STRETCH, 2, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(preview, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_style_text_align(preview , LV_TEXT_ALIGN_LEFT, 0); + updatePreview(); + lv_obj_add_event_cb(slider, [](lv_event_t * e) { + lv_obj_t* slider = lv_event_get_target_obj(e); + SliderParameterInput* self = (SliderParameterInput*)lv_event_get_user_data(e); + self->updatePreview(); + }, LV_EVENT_VALUE_CHANGED, this); + + } + + virtual void updatePreview() override { + char buf[64] = {0}; + lv_snprintf(buf, sizeof(buf), fmt, lv_slider_get_value(slider)); + lv_label_set_text(preview, buf); + } +}; + + +struct SliderSelectParameterInput : public ParameterInput { + static constexpr float SELECT_END = -1; + const float* selections; + const size_t selectionsSize; + + char unit[64] = {0}; + char* fmt; + lv_obj_t* label = nullptr; + lv_obj_t* slider = nullptr; + lv_obj_t* preview = nullptr; + + static constexpr size_t get_selection_num(const float selections[]) { + constexpr size_t MAX_SELECTIONS = 32; + + if (selections) { + for (size_t i = 0; i < MAX_SELECTIONS; ++i) { + if (selections[i] == SELECT_END) { + return i; + } + } + } + return 0; + } + + SliderSelectParameterInput(RadioHandle handle, const RadioParameter param, lv_obj_t* container, int row, const float selections[] = nullptr, char* fmt = "%f") + : ParameterInput(handle, param) + , selections(selections) + , selectionsSize(get_selection_num(selections)) + , fmt(fmt) { + initUi(container, row); + } + + void initUi(lv_obj_t* container, int row) { + label = lv_label_create(container); + lv_label_set_text(label, toString(param)); + lv_obj_set_grid_cell(label, + LV_GRID_ALIGN_STRETCH, 0, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(label, lv_pct(100), LV_SIZE_CONTENT); + + slider = lv_slider_create(container); + lv_obj_set_grid_cell(slider, + LV_GRID_ALIGN_STRETCH, 1, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(slider, lv_pct(100), 10); + lv_slider_set_range(slider, 0, selectionsSize - 1); + + preview = lv_label_create(container); + lv_obj_set_grid_cell(preview, + LV_GRID_ALIGN_STRETCH, 2, 1, + LV_GRID_ALIGN_CENTER, row, 1); + lv_obj_set_size(preview, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_style_text_align(preview , LV_TEXT_ALIGN_LEFT, 0); + + tt_hal_radio_get_parameter_unit_str(handle, param, unit, sizeof(unit)); + updatePreview(); + + lv_obj_add_event_cb(slider, [](lv_event_t * e) { + lv_obj_t* slider = lv_event_get_target_obj(e); + SliderSelectParameterInput* self = (SliderSelectParameterInput*)lv_event_get_user_data(e); + self->updatePreview(); + }, LV_EVENT_VALUE_CHANGED, this); + + } + + virtual void updatePreview() override { + Str text; + text.appendf(fmt, selections[lv_slider_get_value(slider)]); + text.append(unit); + lv_label_set_text(preview, text.c_str()); + } +}; + +static ParameterInput* makeLoraInput(RadioHandle handle, const RadioParameter param, lv_obj_t* container, int row) { + static constexpr float bw_values[] = {7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0, 500.0, SliderSelectParameterInput::SELECT_END}; + switch (param) { + case RADIO_POWER: //no break + case RADIO_FREQUENCY: + return new NumericParameterInput(handle, param, container, row); + case RADIO_BANDWIDTH: + return new SliderSelectParameterInput(handle, param, container, row, bw_values, "%.1f"); + case RADIO_SPREADFACTOR: + return new SliderParameterInput(handle, param, container, row, 7, 12); + case RADIO_CODINGRATE: + return new SliderParameterInput(handle, param, container, row, 5, 8); + case RADIO_SYNCWORD: + return new SliderParameterInput(handle, param, container, row, 0, 255, "%02X"); + case RADIO_PREAMBLES: + return new SliderParameterInput(handle, param, container, row, 0, 0xFFFF); + default: + return new NumericParameterInput(handle, param, container, row); + } +} + +static ParameterInput* makeParameterInput(RadioHandle handle, const RadioParameter param, const Modulation modulation, lv_obj_t* container, int row) { + switch (modulation) { + case MODULATION_LORA: + return makeLoraInput(handle, param, container, row); + default: + return new NumericParameterInput(handle, param, container, row); + } +} + class SettingsView { -private: static constexpr size_t MAX_RADIOS = 32; + static constexpr Modulation FIRST_MODULATION = MODULATION_NONE; + static constexpr Modulation LAST_MODULATION = MODULATION_LRFHSS; + static constexpr size_t MAX_MODEMS = LAST_MODULATION + 1; + static constexpr size_t MAX_PARAMS = RADIO_NARROWGRID + 1; + RadioHandle radios[MAX_RADIOS] = {0}; size_t radioCount = 0; + RadioHandle radioSelected = nullptr; + Modulation modemsAvailable[MAX_MODEMS] = {}; + size_t modemsAvailableCount = 0; + RadioParameter paramsAvailable[MAX_PARAMS] = {}; + ParameterInput* paramInputs[MAX_PARAMS] = {0}; + size_t paramsAvailableCount = 0; + + + lv_obj_t *mainPanel = nullptr; lv_obj_t *deviceForm = nullptr; lv_obj_t *radioDropdown = nullptr; lv_obj_t *radioSwitch = nullptr; + lv_obj_t *modemDropdown = nullptr; lv_obj_t *propertiesForm = nullptr; + public: void queryRadios() { DeviceId devices[MAX_RADIOS]; @@ -68,60 +427,193 @@ public: } } - lv_obj_t* initGridDropdownInput(lv_obj_t *container, int row, const char* const label, const char* const items) { - lv_obj_t* label_obj = lv_label_create(container); - lv_label_set_text(label_obj, label); - lv_obj_set_grid_cell(label_obj, - LV_GRID_ALIGN_STRETCH, 0, 1, - LV_GRID_ALIGN_CENTER, row, 1); - lv_obj_set_size(label_obj, lv_pct(100), LV_SIZE_CONTENT); + int getModemAvailableIndex(Modulation m) { + for (size_t i = 0; i < modemsAvailableCount; ++i) { + if (modemsAvailable[i] == m) { + return i; + } + } + return -1; + } - lv_obj_t* input = lv_dropdown_create(container); - lv_obj_set_grid_cell(input, - LV_GRID_ALIGN_STRETCH, 1, 1, - LV_GRID_ALIGN_CENTER, row, 1); - lv_obj_set_size(input, lv_pct(100), LV_SIZE_CONTENT); - lv_dropdown_set_options(input, items); + lv_obj_t* initParameterFormGeneric(lv_obj_t *parent, const Modulation modem) { + lv_obj_t *container = propertiesForm; + if (container) { + lv_obj_clean(container); + lv_obj_del(container); + } - return input; + paramsAvailableCount = 0; + container = lv_obj_create(parent); + lv_obj_set_style_pad_all(container, 0, 0); + lv_obj_set_layout(container, LV_LAYOUT_GRID); + lv_obj_align(container, LV_ALIGN_TOP_MID, 0, 0); + + const int grid_row_size = 40; + const int grid_col_size = 140; + static constexpr size_t row_dsc_last = RADIO_NARROWGRID + 1; + static lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), grid_col_size, LV_GRID_TEMPLATE_LAST}; + static lv_coord_t row_dsc[row_dsc_last] = {0}; + for (size_t i = 0; i < row_dsc_last; ++i) { + row_dsc[i] = grid_row_size; //LV_GRID_FR(1); + } + row_dsc[row_dsc_last - 1] = LV_GRID_TEMPLATE_LAST; + lv_obj_set_grid_dsc_array(container, col_dsc, row_dsc); + + char unit_buffer[32] = {0}; + for (RadioParameter param = RADIO_POWER; + param <= RADIO_NARROWGRID; + param = static_cast((size_t)param + 1)) { + float value = 0.0; + Str value_buffer; + auto status = tt_hal_radio_get_parameter(radioSelected, param, &value); + if (status == RADIO_PARAM_SUCCESS) { + auto input = makeParameterInput(radioSelected, param, modem, container, paramsAvailableCount); + paramInputs[paramsAvailableCount] = input; + //lv_group_focus_obj(input); + paramsAvailable[paramsAvailableCount] = param; + paramsAvailableCount++; + } + } + row_dsc[paramsAvailableCount] = LV_GRID_TEMPLATE_LAST; + lv_obj_set_grid_dsc_array(container, col_dsc, row_dsc); + lv_obj_set_size(container, lv_pct(100), lv_pct(100)); + + return container; + } + + void selectModulation(int modemIndex) { + lv_dropdown_set_selected(modemDropdown, modemIndex); + if (tt_hal_radio_set_modulation(radioSelected, modemsAvailable[modemIndex])) { + propertiesForm = initParameterFormGeneric(mainPanel, modemsAvailable[modemIndex]); + //clownvomit(propertiesForm); + } + } + + void selectRadio(int index) { + radioSelected = radios[index]; + assert(radioSelected); + + for (size_t i = 0; i < MAX_MODEMS; ++i) { + modemsAvailable[i] = MODULATION_NONE; + } + + Str modulation_list; + modemsAvailableCount = 1; + modemsAvailable[0] = MODULATION_NONE; + modulation_list.append(LV_SYMBOL_MINUS); + modulation_list.append(" "); + modulation_list.append(LV_SYMBOL_MINUS); + modulation_list.append(" "); + modulation_list.append("Disabled\n"); + + + for (Modulation mod = FIRST_MODULATION; + mod <= LAST_MODULATION; + mod = static_cast((size_t)mod + 1)) { + bool canRx = tt_hal_radio_can_receive(radioSelected, mod); + bool canTx = tt_hal_radio_can_transmit(radioSelected, mod); + bool place_sep = (canRx || canTx) && (mod != LAST_MODULATION); + + if (!canRx && !canTx) { + continue; + } + modemsAvailable[modemsAvailableCount] = mod; + modemsAvailableCount++; + + if (canRx) { + modulation_list.append(LV_SYMBOL_DOWNLOAD); + modulation_list.append(" "); + } else { + modulation_list.append(LV_SYMBOL_MINUS); + modulation_list.append(" "); + } + + if (canTx) { + modulation_list.append(LV_SYMBOL_UPLOAD); + modulation_list.append(" "); + } else { + modulation_list.append(LV_SYMBOL_MINUS); + modulation_list.append(" "); + } + + modulation_list.append(toString(mod)); + if (place_sep) { + modulation_list.append("\n"); + } + } + + lv_dropdown_set_options(modemDropdown, modulation_list.c_str()); + auto modemIndexConfigured = getModemAvailableIndex(tt_hal_radio_get_modulation(radioSelected)); + if (modemIndexConfigured > -1) { + lv_dropdown_set_selected(modemDropdown, modemIndexConfigured); + selectModulation(modemIndexConfigured); + } } lv_obj_t *initDeviceForm(lv_obj_t *parent) { lv_obj_t *container = lv_obj_create(parent); - lv_obj_set_size(container, lv_pct(100), lv_pct(100)); + lv_obj_set_size(container, lv_pct(100), LV_SIZE_CONTENT); lv_obj_set_style_pad_all(container, 0, 0); const int grid_row_size = 40; const int grid_col_size = 45; - static lv_coord_t lora_col_dsc[] = {LV_GRID_FR(3), LV_GRID_FR(2), grid_col_size, LV_GRID_TEMPLATE_LAST}; + static lv_coord_t lora_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), grid_col_size, LV_GRID_TEMPLATE_LAST}; static lv_coord_t lora_row_dsc[] = { grid_row_size, grid_row_size, LV_GRID_TEMPLATE_LAST}; + lv_obj_set_layout(container, LV_LAYOUT_GRID); lv_obj_set_grid_dsc_array(container, lora_col_dsc, lora_row_dsc); Str radio_names; getRadioNames(radio_names, "\n"); radioDropdown = initGridDropdownInput(container, 0, "Device", radio_names.c_str()); + modemDropdown = initGridDropdownInput(container, 1, "Modulation", "none available"); radioSwitch = lv_switch_create(container); lv_obj_set_grid_cell(radioSwitch, LV_GRID_ALIGN_STRETCH, 2, 1, LV_GRID_ALIGN_CENTER, 0, 1); lv_obj_set_size(radioSwitch, lv_pct(100), 20); + + lv_obj_add_event_cb(modemDropdown, [](lv_event_t * e) { + SettingsView* self = (SettingsView*)lv_event_get_user_data(e); + lv_obj_t* input = lv_event_get_target_obj(e); + self->selectModulation(lv_dropdown_get_selected(input)); + }, LV_EVENT_VALUE_CHANGED, this); + + selectRadio(0); return container; } void initUi(lv_obj_t *parent) { - lv_obj_t *container = lv_obj_create(parent); - lv_obj_set_size(container, lv_pct(100), lv_pct(80)); - lv_obj_set_flex_flow(container, LV_FLEX_FLOW_COLUMN); - lv_obj_align(container, LV_ALIGN_TOP_MID, 0, 0); - lv_obj_set_style_border_width(container, 0, 0); - lv_obj_set_style_pad_all(container, 0, 0); + mainPanel = lv_obj_create(parent); + lv_obj_set_size(mainPanel, lv_pct(100), lv_pct(80)); + lv_obj_set_flex_flow(mainPanel, LV_FLEX_FLOW_COLUMN); + lv_obj_align(mainPanel, LV_ALIGN_TOP_MID, 0, 0); + lv_obj_set_style_border_width(mainPanel, 0, 0); + lv_obj_set_style_pad_all(mainPanel, 0, 0); // Only needed if container needs to be scrollable through encoder long long press - //lv_obj_add_flag(container, (lv_obj_flag_t)(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLL_ON_FOCUS)); - deviceForm = initDeviceForm(container); + lv_obj_add_flag(mainPanel, (lv_obj_flag_t)(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLL_ON_FOCUS)); + auto* group = lv_group_get_default(); + lv_group_add_obj(group, mainPanel); + //lv_obj_add_event_cb(btn, scrollbar_highlight, LV_EVENT_FOCUS, NULL); + //lv_obj_add_event_cb(btn, scrollbar_restore, LV_EVENT_DEFOCUSED, NULL); + + // Create once (e.g. during init) + static lv_style_t style_scroll_focus; + lv_style_init(&style_scroll_focus); + lv_style_set_bg_color(&style_scroll_focus, lv_color_make(0x40,0xA0,0xFF)); + lv_style_set_bg_opa(&style_scroll_focus, LV_OPA_COVER); + lv_style_set_border_width(&style_scroll_focus, 1); + lv_style_set_border_color(&style_scroll_focus, lv_color_black()); + + // Apply style targeted to the scrollbar part when the object is FOCUSED + // LV_PART_SCROLLBAR | LV_STATE_FOCUSED will ensure the style is used only while focused. + lv_obj_add_style(mainPanel, &style_scroll_focus, LV_PART_SCROLLBAR | LV_STATE_FOCUSED); + + deviceForm = initDeviceForm(mainPanel); } explicit SettingsView(lv_obj_t *parent) { @@ -141,12 +633,13 @@ void RadioSet::onShow(AppHandle appHandle, lv_obj_t* parent) { uiDropDownMenu = lv_dropdown_create(toolbar); lv_dropdown_set_options(uiDropDownMenu, LV_SYMBOL_ENVELOPE " Terminal\n" LV_SYMBOL_SETTINGS " Settings"); - lv_dropdown_set_text(uiDropDownMenu, "Main Menu"); + lv_dropdown_set_text(uiDropDownMenu, "Menu"); lv_dropdown_set_symbol(uiDropDownMenu, LV_SYMBOL_DOWN); lv_dropdown_set_selected_highlight(uiDropDownMenu, true); lv_obj_set_style_border_color(uiDropDownMenu, lv_color_hex(0xFAFAFA), LV_PART_MAIN); lv_obj_set_style_border_width(uiDropDownMenu, 1, LV_PART_MAIN); lv_obj_align(uiDropDownMenu, LV_ALIGN_RIGHT_MID, 0, 0); + lv_obj_set_width(uiDropDownMenu, 120); lv_obj_t* wrapper = lv_obj_create(parent); lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN); diff --git a/ExternalApps/RadioSet/manifest.properties b/ExternalApps/RadioSet/manifest.properties index c459aed1..19acc9b3 100644 --- a/ExternalApps/RadioSet/manifest.properties +++ b/ExternalApps/RadioSet/manifest.properties @@ -6,8 +6,8 @@ platforms=esp32,esp32s3 [app] id=com.d49406.RadioSet version=0.0.1 -name=RadioSet -description=Receive and transmit radio messages +name=Radio Terminal +description=Receive and transmit radio packages [author] name=Dominic Hoeglinger -website=https://git.hoeglinger.eu +website=https://github.com/ByteWelder/Tactility