diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index c886b50f..24d15adc 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -44,6 +44,7 @@ namespace fs = std::filesystem; #include "string_format.hpp" #include "ui_styles.hpp" +#include "ui_font_fixed_8x16.hpp" #include "cpld_update.hpp" #include "config_mode.hpp" @@ -757,7 +758,7 @@ void SetConfigModeView::focus() { button_save.focus(); } -/* FakeBrightnessView ************************************/ +/* SetFakeBrightnessView ************************************/ SetFakeBrightnessView::SetFakeBrightnessView(NavigationView& nav) { add_children({&labels, @@ -785,6 +786,53 @@ void SetFakeBrightnessView::focus() { button_save.focus(); } +/* SetMenuColorView ************************************/ + +void SetMenuColorView::paint_sample() { + Color c = Color(field_red_level.value(), field_green_level.value(), field_blue_level.value()); + button_sample.set_bg_color(c); +} + +SetMenuColorView::SetMenuColorView(NavigationView& nav) { + add_children({&labels, + &button_sample, + &field_red_level, + &field_green_level, + &field_blue_level, + &button_save, + &button_cancel}); + + button_sample.set_focusable(false); + + Color c = pmem::menu_color(); + field_red_level.set_value(c.r()); + field_green_level.set_value(c.g()); + field_blue_level.set_value(c.b()); + paint_sample(); + + const auto color_changed_fn = [this](int32_t) { + paint_sample(); + }; + field_red_level.on_change = color_changed_fn; + field_green_level.on_change = color_changed_fn; + field_blue_level.on_change = color_changed_fn; + + button_save.on_select = [&nav, this](Button&) { + Color c = Color(field_red_level.value(), field_green_level.value(), field_blue_level.value()); + pmem::set_menu_color(c); + send_system_refresh(); + nav.pop(); + }; + + button_cancel.on_select = [&nav, this](Button&) { + nav.pop(); + }; +} + +void SetMenuColorView::focus() { + button_save.focus(); +} + /* SettingsMenuView **************************************/ SettingsMenuView::SettingsMenuView(NavigationView& nav) { @@ -806,6 +854,7 @@ SettingsMenuView::SettingsMenuView(NavigationView& nav) { {"User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav]() { nav.push(); }}, {"QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav]() { nav.push(); }}, {"Brightness", ui::Color::dark_cyan(), &bitmap_icon_brightness, [&nav]() { nav.push(); }}, + {"Menu Color", ui::Color::dark_cyan(), &bitmap_icon_brightness, [&nav]() { nav.push(); }}, }); set_max_rows(2); // allow wider buttons } diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index 0f50e101..83ef294d 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -588,7 +588,7 @@ class SetEncoderDialView : public View { NumberField field_encoder_rate_multiplier{ {20 * 8, 12 * 16}, 2, - {1, 10}, + {1, 15}, 1, ' '}; @@ -731,6 +731,64 @@ class SetFakeBrightnessView : public View { }; }; +class SetMenuColorView : public View { + public: + SetMenuColorView(NavigationView& nav); + + void focus() override; + + std::string title() const override { return "Menu Color"; }; + + private: + void paint_sample(); + + Labels labels{ + {{3 * 8, 1 * 16}, "Menu Button Color Scheme", Color::light_grey()}, + {{2 * 8, 8 * 16}, "Red Level:", Color::light_grey()}, + {{2 * 8, 9 * 16}, "Green Level:", Color::light_grey()}, + {{2 * 8, 10 * 16}, "Blue Level:", Color::light_grey()}, + }; + + NewButton button_sample{ + {8 * 8, 4 * 16, 14 * 8, 3 * 16}, + "New Color", + &bitmap_icon_brightness, + }; + + NumberField field_red_level{ + {15 * 8, 8 * 16}, + 3, + {8, 248}, + 8, + ' ', + }; + + NumberField field_green_level{ + {15 * 8, 9 * 16}, + 3, + {8, 248}, + 8, + ' ', + }; + + NumberField field_blue_level{ + {15 * 8, 10 * 16}, + 3, + {8, 248}, + 8, + ' ', + }; + + Button button_save{ + {2 * 8, 16 * 16, 12 * 8, 32}, + "Save"}; + + Button button_cancel{ + {16 * 8, 16 * 16, 12 * 8, 32}, + "Cancel", + }; +}; + class SettingsMenuView : public BtnGridView { public: SettingsMenuView(NavigationView& nav); diff --git a/firmware/application/ui/ui_btngrid.cpp b/firmware/application/ui/ui_btngrid.cpp index 871ea92f..92891e85 100644 --- a/firmware/application/ui/ui_btngrid.cpp +++ b/firmware/application/ui/ui_btngrid.cpp @@ -127,6 +127,7 @@ void BtnGridView::add_item(GridItem new_item) { void BtnGridView::update_items() { size_t i = 0; + Color bg_color = portapack::persistent_memory::menu_color(); if ((menu_items.size()) > (displayed_max + offset)) { more = true; @@ -147,6 +148,7 @@ void BtnGridView::update_items() { item->set_text(menu_items[i + offset].text); item->set_bitmap(menu_items[i + offset].bitmap); item->set_color(menu_items[i + offset].color); + item->set_bg_color(bg_color); item->on_select = menu_items[i + offset].on_select; item->set_dirty(); } @@ -171,10 +173,12 @@ bool BtnGridView::set_highlighted(int32_t new_value) { if (((uint32_t)new_value > offset) && ((new_value - offset) >= displayed_max)) { // Shift BtnGridView up highlighted_item = new_value; - offset += rows_; + // rounding up new offset to next multiple of rows + offset = new_value - displayed_max + rows_; + offset -= (offset % rows_); update_items(); // refresh whole screen (display flickers) only if scrolling last row up and a blank button is needed at the bottom - if ((new_value + rows_ > item_count) && (item_count % rows_) != 0) + if ((new_value + rows_ >= item_count) && (item_count % rows_) != 0) set_dirty(); } else if ((uint32_t)new_value < offset) { // Shift BtnGridView down diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 37740bba..c7d74705 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -31,6 +31,7 @@ #include "memory_map.hpp" #include "portapack.hpp" #include "string_format.hpp" +#include "ui.hpp" #include "ui_styles.hpp" #include "ui_painter.hpp" #include "ui_flash_utility.hpp" @@ -46,6 +47,7 @@ #include using namespace std; +using namespace ui; namespace portapack { namespace persistent_memory { @@ -248,6 +250,11 @@ struct data_t { // Daylight savings time dst_config_t dst_config; + // Menu Color Scheme + Color menu_color; + + uint16_t UNUSED_16; + constexpr data_t() : structure_version(data_structure_version_enum::VERSION_CURRENT), target_frequency(target_frequency_reset_value), @@ -304,7 +311,9 @@ struct data_t { misc_config(), ui_config2(), config_mode_storage(CONFIG_MODE_NORMAL_VALUE), - dst_config() { + dst_config(), + menu_color(Color::grey()), + UNUSED_16() { } }; @@ -412,6 +421,7 @@ void defaults() { set_config_disable_external_tcxo(false); set_encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL); set_config_speaker_disable(true); // Disable AK4951 speaker by default (in case of OpenSourceSDRLab H2) + set_menu_color(Color::grey()); // Default values for recon app. set_recon_autosave_freqs(false); @@ -461,6 +471,7 @@ void init() { // Firmware upgrade handling - adjust newly defined fields where 0 is an invalid default if (fake_brightness_level() == 0) set_fake_brightness_level(BRIGHTNESS_50); + if (menu_color().v == 0) set_menu_color(Color::grey()); } void persist() { @@ -1052,6 +1063,14 @@ void toggle_fake_brightness_level() { } } +// Menu Color Scheme +Color menu_color() { + return data->menu_color; +} +void set_menu_color(Color v) { + data->menu_color = v; +} + // PMem to sdcard settings bool should_use_sdcard_for_pmem() { @@ -1158,6 +1177,7 @@ bool debug_dump() { pmem_dump_file.write_line("config_mode_storage: 0x" + to_string_hex(data->config_mode_storage, 8)); pmem_dump_file.write_line("dst_config: 0x" + to_string_hex((uint32_t)data->dst_config.v, 8)); pmem_dump_file.write_line("fake_brightness_level: " + to_string_dec_uint(data->fake_brightness_level)); + pmem_dump_file.write_line("menu_color: 0x" + to_string_hex(data->menu_color.v, 4)); // ui_config bits const auto backlight_timer = portapack::persistent_memory::config_backlight_timer(); diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 0a1b42f8..7a857e86 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -34,6 +34,7 @@ #include "serializer.hpp" #include "volume.hpp" #include "config_mode.hpp" +#include "ui.hpp" // persistent memory from/to sdcard flag file #define PMEM_FILEFLAG u"/SETTINGS/PMEM_FILEFLAG" @@ -46,6 +47,7 @@ using namespace modems; using namespace serializer; +using namespace ui; namespace portapack { @@ -282,6 +284,9 @@ uint8_t fake_brightness_level(); void set_fake_brightness_level(uint8_t v); void toggle_fake_brightness_level(); +Color menu_color(); +void set_menu_color(Color v); + /* Recon app */ bool recon_autosave_freqs(); bool recon_autostart_recon(); diff --git a/firmware/common/ui.hpp b/firmware/common/ui.hpp index 2f4890b4..36a7b837 100644 --- a/firmware/common/ui.hpp +++ b/firmware/common/ui.hpp @@ -78,6 +78,18 @@ struct Color { ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3))} { } + uint8_t r() { + return (uint8_t)((v >> 8) & 0xf8); + } + + uint8_t g() { + return (uint8_t)((v >> 3) & 0xfc); + } + + uint8_t b() { + return (uint8_t)((v << 3) & 0xf8); + } + uint8_t to_greyscale() { uint32_t r = (v >> 8) & 0xf8; uint32_t g = (v >> 3) & 0xfc; diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 0d9d78a5..25bee4d6 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -1290,6 +1290,11 @@ void NewButton::set_color(Color color) { set_dirty(); } +void NewButton::set_bg_color(Color color) { + bg_color_ = color; + set_dirty(); +} + void NewButton::set_vertical_center(bool value) { vertical_center_ = value; set_dirty(); @@ -1343,7 +1348,7 @@ Style NewButton::paint_style() { s.background = style().foreground; s.foreground = Color::black(); } else { - s.background = Color::grey(); + s.background = bg_color_; s.foreground = style().foreground; } diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 5b57cd2e..f0109d1c 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -504,6 +504,7 @@ class NewButton : public Widget { void set_bitmap(const Bitmap* bitmap); void set_text(const std::string value); void set_color(Color value); + void set_bg_color(Color value); void set_vertical_center(bool value); std::string text() const; const Bitmap* bitmap(); @@ -522,6 +523,7 @@ class NewButton : public Widget { protected: virtual Style paint_style(); Color color_; + Color bg_color_{Color::light_grey()}; private: std::string text_;