diff --git a/src/ui/include/modal_add_to_queue.hpp b/src/ui/include/modal_add_to_queue.hpp index 760a155e..79f804a4 100644 --- a/src/ui/include/modal_add_to_queue.hpp +++ b/src/ui/include/modal_add_to_queue.hpp @@ -30,6 +30,10 @@ class AddToQueue : public Modal { audio::TrackQueue& queue_; std::shared_ptr item_; lv_obj_t* container_; + + lv_obj_t* selected_track_btn_; + lv_obj_t* all_tracks_btn_; + bool all_tracks_; }; } // namespace modals diff --git a/src/ui/include/themes.hpp b/src/ui/include/themes.hpp index ee4bb05d..d7a5261a 100644 --- a/src/ui/include/themes.hpp +++ b/src/ui/include/themes.hpp @@ -5,7 +5,16 @@ namespace ui { namespace themes { -enum class Style { kMenuItem, kTopBar }; +enum class Style { + kMenuItem, + kMenuSubheadFirst, + kMenuSubhead, + kTopBar, + kPopup, + kTab, + kButtonPrimary, +}; + class Theme { public: void Apply(void); diff --git a/src/ui/modal.cpp b/src/ui/modal.cpp index 36376093..3cab85f5 100644 --- a/src/ui/modal.cpp +++ b/src/ui/modal.cpp @@ -21,6 +21,7 @@ #include "index.hpp" #include "misc/lv_area.h" #include "screen.hpp" +#include "themes.hpp" #include "ui_events.hpp" #include "ui_fsm.hpp" #include "widget_top_bar.hpp" @@ -40,6 +41,8 @@ Modal::Modal(Screen* host) lv_obj_set_style_bg_opa(root_, LV_OPA_COVER, 0); lv_obj_set_style_bg_color(root_, lv_color_white(), 0); + themes::Theme::instance()->ApplyStyle(root_, themes::Style::kPopup); + host_->modal_group(group_); } diff --git a/src/ui/modal_add_to_queue.cpp b/src/ui/modal_add_to_queue.cpp index 649ba3bd..b84d8571 100644 --- a/src/ui/modal_add_to_queue.cpp +++ b/src/ui/modal_add_to_queue.cpp @@ -14,13 +14,17 @@ #include "core/lv_group.h" #include "core/lv_obj_pos.h" #include "event_queue.hpp" +#include "extra/layouts/flex/lv_flex.h" #include "extra/widgets/list/lv_list.h" #include "extra/widgets/menu/lv_menu.h" #include "extra/widgets/spinner/lv_spinner.h" +#include "extra/widgets/tabview/lv_tabview.h" #include "hal/lv_hal_disp.h" #include "index.hpp" #include "misc/lv_area.h" +#include "misc/lv_color.h" #include "source.hpp" +#include "themes.hpp" #include "track_queue.hpp" #include "ui_events.hpp" #include "ui_fsm.hpp" @@ -34,15 +38,12 @@ namespace modals { AddToQueue::AddToQueue(Screen* host, audio::TrackQueue& queue, std::shared_ptr item) - : Modal(host), queue_(queue), item_(item) { + : Modal(host), queue_(queue), item_(item), all_tracks_(0) { lv_obj_set_layout(root_, LV_LAYOUT_FLEX); lv_obj_set_flex_flow(root_, LV_FLEX_FLOW_COLUMN); - lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, + lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER); - lv_obj_t* label = lv_label_create(root_); - lv_label_set_text(label, "This track"); - lv_obj_t* button_container = lv_obj_create(root_); lv_obj_set_size(button_container, lv_pct(100), LV_SIZE_CONTENT); lv_obj_set_layout(button_container, LV_LAYOUT_FLEX); @@ -50,16 +51,56 @@ AddToQueue::AddToQueue(Screen* host, lv_obj_set_flex_align(button_container, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + selected_track_btn_ = lv_btn_create(button_container); + lv_obj_t* label = lv_label_create(selected_track_btn_); + lv_label_set_text(label, "Selected"); + lv_group_add_obj(group_, selected_track_btn_); + lv_obj_add_state(selected_track_btn_, LV_STATE_CHECKED); + themes::Theme::instance()->ApplyStyle(selected_track_btn_, + themes::Style::kTab); + + lv_bind(selected_track_btn_, LV_EVENT_CLICKED, [this](lv_obj_t*) { + lv_obj_add_state(selected_track_btn_, LV_STATE_CHECKED); + lv_obj_clear_state(all_tracks_btn_, LV_STATE_CHECKED); + all_tracks_ = false; + }); + + all_tracks_btn_ = lv_btn_create(button_container); + label = lv_label_create(all_tracks_btn_); + lv_label_set_text(label, "All tracks"); + lv_group_add_obj(group_, all_tracks_btn_); + themes::Theme::instance()->ApplyStyle(all_tracks_btn_, themes::Style::kTab); + + lv_bind(all_tracks_btn_, LV_EVENT_CLICKED, [this](lv_obj_t*) { + lv_obj_clear_state(selected_track_btn_, LV_STATE_CHECKED); + lv_obj_add_state(all_tracks_btn_, LV_STATE_CHECKED); + all_tracks_ = true; + }); + + lv_obj_t* spacer = lv_obj_create(root_); + lv_obj_set_size(spacer, 1, 4); + + button_container = lv_obj_create(root_); + lv_obj_set_size(button_container, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_layout(button_container, LV_LAYOUT_FLEX); + lv_obj_set_flex_flow(button_container, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(button_container, LV_FLEX_ALIGN_SPACE_EVENLY, + LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_t* btn = lv_btn_create(button_container); label = lv_label_create(btn); - lv_label_set_text(label, "Play"); + lv_label_set_text(label, "Play now"); lv_group_add_obj(group_, btn); lv_bind(btn, LV_EVENT_CLICKED, [this](lv_obj_t*) { queue_.Clear(); - auto track = item_->Current(); - if (track) { - queue_.AddNext(*track); + if (all_tracks_) { + queue_.IncludeNext(item_); + } else { + auto track = item_->Current(); + if (track) { + queue_.AddNext(*track); + } } events::Ui().Dispatch(internal::ModalCancelPressed{}); }); @@ -67,56 +108,64 @@ AddToQueue::AddToQueue(Screen* host, bool has_queue = queue.GetCurrent().has_value(); if (has_queue) { + label = lv_label_create(root_); + lv_label_set_text(label, "Enqueue"); + + spacer = lv_obj_create(root_); + lv_obj_set_size(spacer, 1, 4); + + button_container = lv_obj_create(root_); + lv_obj_set_size(button_container, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_layout(button_container, LV_LAYOUT_FLEX); + lv_obj_set_flex_flow(button_container, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(button_container, LV_FLEX_ALIGN_SPACE_EVENLY, + LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + btn = lv_btn_create(button_container); label = lv_label_create(btn); - lv_label_set_text(label, "Enqueue"); + lv_label_set_text(label, "Next"); lv_group_add_obj(group_, btn); lv_bind(btn, LV_EVENT_CLICKED, [this](lv_obj_t*) { - auto track = item_->Current(); - if (track) { - queue_.AddLast(*track); + if (all_tracks_) { + queue_.IncludeNext(item_); + } else { + queue_.AddNext(item_->Current().value()); } events::Ui().Dispatch(internal::ModalCancelPressed{}); }); - } - label = lv_label_create(root_); - lv_label_set_text(label, "All tracks"); - button_container = lv_obj_create(root_); - lv_obj_set_size(button_container, lv_pct(100), LV_SIZE_CONTENT); - lv_obj_set_layout(button_container, LV_LAYOUT_FLEX); - lv_obj_set_flex_flow(button_container, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(button_container, LV_FLEX_ALIGN_SPACE_EVENLY, - LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - - btn = lv_btn_create(button_container); - label = lv_label_create(btn); - lv_label_set_text(label, "Play"); - lv_group_add_obj(group_, btn); - - lv_bind(btn, LV_EVENT_CLICKED, [this](lv_obj_t*) { - queue_.Clear(); - queue_.IncludeNext(item_); - events::Ui().Dispatch(internal::ModalCancelPressed{}); - }); - - if (has_queue) { btn = lv_btn_create(button_container); label = lv_label_create(btn); - lv_label_set_text(label, "Enqueue"); + lv_label_set_text(label, "Last"); lv_group_add_obj(group_, btn); lv_bind(btn, LV_EVENT_CLICKED, [this](lv_obj_t*) { - queue_.IncludeLast(item_); + if (all_tracks_) { + queue_.IncludeLast(item_); + } else { + queue_.AddLast(item_->Current().value()); + } events::Ui().Dispatch(internal::ModalCancelPressed{}); }); } - btn = lv_btn_create(root_); + spacer = lv_obj_create(root_); + lv_obj_set_size(spacer, 1, 4); + + button_container = lv_obj_create(root_); + lv_obj_set_size(button_container, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_layout(button_container, LV_LAYOUT_FLEX); + lv_obj_set_flex_flow(button_container, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(button_container, LV_FLEX_ALIGN_END, + LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + + btn = lv_btn_create(button_container); label = lv_label_create(btn); lv_label_set_text(label, "Cancel"); lv_group_add_obj(group_, btn); + lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_RED), + LV_PART_MAIN); lv_bind(btn, LV_EVENT_CLICKED, [](lv_obj_t*) { events::Ui().Dispatch(internal::ModalCancelPressed{}); diff --git a/src/ui/screen.cpp b/src/ui/screen.cpp index bdc30fcd..7cc37680 100644 --- a/src/ui/screen.cpp +++ b/src/ui/screen.cpp @@ -76,6 +76,8 @@ MenuScreen::MenuScreen(models::TopBar& top_bar_model, lv_obj_set_flex_flow(content_, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(content_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + + lv_obj_set_style_pad_all(content_, 4, LV_PART_MAIN); } } // namespace ui diff --git a/src/ui/screen_menu.cpp b/src/ui/screen_menu.cpp index 44f49b32..037e1156 100644 --- a/src/ui/screen_menu.cpp +++ b/src/ui/screen_menu.cpp @@ -17,6 +17,7 @@ #include "extra/widgets/spinner/lv_spinner.h" #include "hal/lv_hal_disp.h" #include "index.hpp" +#include "lv_api_map.h" #include "misc/lv_area.h" #include "model_top_bar.hpp" #include "ui_events.hpp" diff --git a/src/ui/screen_playing.cpp b/src/ui/screen_playing.cpp index 6b054f7f..d7fda0b6 100644 --- a/src/ui/screen_playing.cpp +++ b/src/ui/screen_playing.cpp @@ -127,7 +127,7 @@ Playing::Playing(models::TopBar& top_bar_model, lv_obj_set_layout(above_fold_container, LV_LAYOUT_FLEX); lv_obj_set_size(above_fold_container, lv_pct(100), lv_disp_get_ver_res(NULL)); lv_obj_set_flex_flow(above_fold_container, LV_FLEX_FLOW_COLUMN); - lv_obj_set_flex_align(above_fold_container, LV_FLEX_ALIGN_SPACE_BETWEEN, + lv_obj_set_flex_align(above_fold_container, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); widgets::TopBar::Configuration config{ @@ -136,7 +136,18 @@ Playing::Playing(models::TopBar& top_bar_model, }; CreateTopBar(above_fold_container, config, top_bar_model); - lv_obj_t* info_container = lv_obj_create(above_fold_container); + lv_obj_t* now_playing_container = lv_obj_create(above_fold_container); + lv_obj_set_layout(now_playing_container, LV_LAYOUT_FLEX); + lv_obj_set_width(now_playing_container, lv_pct(100)); + lv_obj_set_flex_grow(now_playing_container, 1); + lv_obj_set_flex_flow(now_playing_container, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(now_playing_container, LV_FLEX_ALIGN_SPACE_BETWEEN, + LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + + lv_obj_set_style_pad_left(now_playing_container, 4, LV_PART_MAIN); + lv_obj_set_style_pad_right(now_playing_container, 4, LV_PART_MAIN); + + lv_obj_t* info_container = lv_obj_create(now_playing_container); lv_obj_set_layout(info_container, LV_LAYOUT_FLEX); lv_obj_set_width(info_container, lv_pct(100)); lv_obj_set_flex_grow(info_container, 1); @@ -148,7 +159,7 @@ Playing::Playing(models::TopBar& top_bar_model, lv_obj_t* album_label = info_label(info_container); lv_obj_t* title_label = info_label(info_container); - lv_obj_t* scrubber = lv_slider_create(above_fold_container); + lv_obj_t* scrubber = lv_slider_create(now_playing_container); lv_obj_set_size(scrubber, lv_pct(100), 5); lv_style_init(&scrubber_style); @@ -199,7 +210,10 @@ Playing::Playing(models::TopBar& top_bar_model, playback_model.current_track_position.onChangedAndNow( [=](uint32_t p) { lv_slider_set_value(scrubber, p, LV_ANIM_OFF); })); - lv_obj_t* controls_container = lv_obj_create(above_fold_container); + lv_obj_t* spacer = lv_obj_create(now_playing_container); + lv_obj_set_size(spacer, 1, 4); + + lv_obj_t* controls_container = lv_obj_create(now_playing_container); lv_obj_set_size(controls_container, lv_pct(100), 20); lv_obj_set_flex_flow(controls_container, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(controls_container, LV_FLEX_ALIGN_SPACE_EVENLY, @@ -226,7 +240,7 @@ Playing::Playing(models::TopBar& top_bar_model, lv_group_add_obj(group_, control_button(controls_container, LV_SYMBOL_LOOP)); - next_up_header_ = lv_obj_create(above_fold_container); + next_up_header_ = lv_obj_create(now_playing_container); lv_obj_set_size(next_up_header_, lv_pct(100), 15); lv_obj_set_flex_flow(next_up_header_, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(next_up_header_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END, @@ -325,8 +339,9 @@ auto Playing::OnFocusAboveFold() -> void { } auto Playing::OnFocusBelowFold() -> void { - if (lv_obj_get_scroll_y(content_) < lv_obj_get_y(next_up_header_)) { - lv_obj_scroll_to_y(content_, lv_obj_get_y(next_up_header_), LV_ANIM_ON); + if (lv_obj_get_scroll_y(content_) < lv_obj_get_y(next_up_header_) + 20) { + lv_obj_scroll_to_y(content_, lv_obj_get_y(next_up_header_) + 20, + LV_ANIM_ON); } } diff --git a/src/ui/screen_settings.cpp b/src/ui/screen_settings.cpp index a661392f..021b5bfc 100644 --- a/src/ui/screen_settings.cpp +++ b/src/ui/screen_settings.cpp @@ -27,11 +27,13 @@ #include "extra/widgets/spinner/lv_spinner.h" #include "hal/lv_hal_disp.h" #include "index.hpp" +#include "lv_api_map.h" #include "misc/lv_anim.h" #include "misc/lv_area.h" #include "model_top_bar.hpp" #include "nvs.hpp" #include "screen.hpp" +#include "themes.hpp" #include "ui_events.hpp" #include "ui_fsm.hpp" #include "widget_top_bar.hpp" @@ -69,15 +71,18 @@ Settings::Settings(models::TopBar& bar) : MenuScreen(bar, "Settings") { lv_obj_t* list = lv_list_create(content_); lv_obj_set_size(list, lv_pct(100), lv_pct(100)); - lv_list_add_text(list, "Audio"); + themes::Theme::instance()->ApplyStyle(lv_list_add_text(list, "Audio"), + themes::Style::kMenuSubheadFirst); sub_menu(list, group_, "Bluetooth", Page::kBluetooth); sub_menu(list, group_, "Headphones", Page::kHeadphones); - lv_list_add_text(list, "Interface"); + themes::Theme::instance()->ApplyStyle(lv_list_add_text(list, "Interface"), + themes::Style::kMenuSubhead); sub_menu(list, group_, "Appearance", Page::kAppearance); sub_menu(list, group_, "Input Method", Page::kInput); - lv_list_add_text(list, "System"); + themes::Theme::instance()->ApplyStyle(lv_list_add_text(list, "System"), + themes::Style::kMenuSubhead); sub_menu(list, group_, "Storage", Page::kStorage); sub_menu(list, group_, "Firmware Update", Page::kFirmwareUpdate); sub_menu(list, group_, "About", Page::kAbout); @@ -281,10 +286,13 @@ Headphones::Headphones(models::TopBar& bar, drivers::NvsStorage& nvs) lv_obj_t* vol_label = lv_label_create(content_); lv_label_set_text(vol_label, "Volume Limit"); lv_obj_t* vol_dropdown = lv_dropdown_create(content_); - lv_dropdown_set_options(vol_dropdown, - "Line Level (-10 dB)\nCD Level (+6 dB)\nMax " - "before clipping (+10dB)\nCustom"); + lv_obj_set_width(vol_dropdown, lv_pct(100)); + lv_dropdown_set_options( + vol_dropdown, + "Line Level (-10 dB)\nCD Level (+6 dB)\nMaximum (+10dB)\nCustom"); lv_group_add_obj(group_, vol_dropdown); + themes::Theme::instance()->ApplyStyle(lv_dropdown_get_list(vol_dropdown), + themes::Style::kPopup); uint16_t level = nvs.AmpMaxVolume(); for (int i = 0; i < index_to_level_.size() + 1; i++) { @@ -318,10 +326,17 @@ Headphones::Headphones(models::TopBar& bar, drivers::NvsStorage& nvs) lv_obj_add_flag(custom_vol_container_, LV_OBJ_FLAG_HIDDEN); } + lv_obj_t* spacer = lv_obj_create(content_); + lv_obj_set_size(spacer, 1, 4); + lv_obj_t* balance_label = lv_label_create(content_); lv_label_set_text(balance_label, "Left/Right Balance"); + + spacer = lv_obj_create(content_); + lv_obj_set_size(spacer, 1, 4); + lv_obj_t* balance = lv_slider_create(content_); - lv_obj_set_width(balance, lv_pct(100)); + lv_obj_set_size(balance, lv_pct(100), 5); lv_slider_set_range(balance, -10, 10); lv_slider_set_value(balance, 0, LV_ANIM_OFF); lv_slider_set_mode(balance, LV_SLIDER_MODE_SYMMETRICAL); @@ -329,6 +344,8 @@ Headphones::Headphones(models::TopBar& bar, drivers::NvsStorage& nvs) lv_obj_t* current_balance_label = lv_label_create(content_); lv_label_set_text(current_balance_label, "0dB"); lv_obj_set_size(current_balance_label, lv_pct(100), LV_SIZE_CONTENT); + + lv_obj_move_foreground(lv_dropdown_get_list(vol_dropdown)); } auto Headphones::ChangeMaxVolume(uint8_t index) -> void { @@ -396,7 +413,7 @@ Appearance::Appearance(models::TopBar& bar, lv_obj_t* brightness_label = lv_label_create(content_); lv_label_set_text(brightness_label, "Brightness"); lv_obj_t* brightness = lv_slider_create(content_); - lv_obj_set_width(brightness, lv_pct(100)); + lv_obj_set_size(brightness, lv_pct(100), 5); lv_slider_set_range(brightness, 10, 100); lv_slider_set_value(brightness, initial_brightness, LV_ANIM_OFF); lv_group_add_obj(group_, brightness); @@ -434,6 +451,8 @@ InputMethod::InputMethod(models::TopBar& bar, drivers::NvsStorage& nvs) lv_dropdown_set_selected(primary_dropdown, static_cast(nvs.PrimaryInput())); + themes::Theme::instance()->ApplyStyle(lv_dropdown_get_list(primary_dropdown), + themes::Style::kPopup); lv_bind(primary_dropdown, LV_EVENT_VALUE_CHANGED, [this](lv_obj_t* obj) { drivers::NvsStorage::InputModes mode; @@ -467,10 +486,19 @@ Storage::Storage(models::TopBar& bar) : MenuScreen(bar, "Storage") { lv_bar_set_range(usage_bar, 0, 32); lv_bar_set_value(usage_bar, 6, LV_ANIM_OFF); - lv_obj_t* reset_btn = lv_btn_create(content_); + lv_obj_t* container = lv_obj_create(content_); + lv_obj_set_size(container, lv_pct(100), 30); + lv_obj_set_layout(container, LV_LAYOUT_FLEX); + lv_obj_set_flex_flow(container, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(container, LV_FLEX_ALIGN_SPACE_EVENLY, + LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + + lv_obj_t* reset_btn = lv_btn_create(container); lv_obj_t* reset_label = lv_label_create(reset_btn); lv_label_set_text(reset_label, "Update Database"); lv_group_add_obj(group_, reset_btn); + themes::Theme::instance()->ApplyStyle(reset_btn, + themes::Style::kButtonPrimary); lv_bind(reset_btn, LV_EVENT_CLICKED, [&](lv_obj_t*) { events::Ui().Dispatch(internal::ReindexDatabase{}); @@ -479,18 +507,35 @@ Storage::Storage(models::TopBar& bar) : MenuScreen(bar, "Storage") { FirmwareUpdate::FirmwareUpdate(models::TopBar& bar) : MenuScreen(bar, "Firmware Update") { - label_pair(content_, "ESP32 FW:", "vIDKLOL"); + lv_obj_set_flex_align(content_, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, + LV_FLEX_ALIGN_CENTER); + label_pair(content_, "SAMD21 FW:", "vIDKLOL"); + lv_obj_t* spacer = lv_obj_create(content_); + lv_obj_set_size(spacer, 1, 4); + lv_obj_t* flash_esp_btn = lv_btn_create(content_); lv_obj_t* flash_esp_label = lv_label_create(flash_esp_btn); - lv_label_set_text(flash_esp_label, "Update ESP32"); + lv_label_set_text(flash_esp_label, "Update"); lv_group_add_obj(group_, flash_esp_btn); + themes::Theme::instance()->ApplyStyle(flash_esp_btn, + themes::Style::kButtonPrimary); + + spacer = lv_obj_create(content_); + lv_obj_set_size(spacer, 1, 8); + + label_pair(content_, "ESP32 FW:", "vIDKLOL"); + + spacer = lv_obj_create(content_); + lv_obj_set_size(spacer, 1, 4); lv_obj_t* flash_samd_btn = lv_btn_create(content_); lv_obj_t* flash_samd_label = lv_label_create(flash_samd_btn); - lv_label_set_text(flash_samd_label, "Update SAMD21"); + lv_label_set_text(flash_samd_label, "Update"); lv_group_add_obj(group_, flash_samd_btn); + themes::Theme::instance()->ApplyStyle(flash_samd_btn, + themes::Style::kButtonPrimary); } About::About(models::TopBar& bar) : MenuScreen(bar, "About") { diff --git a/src/ui/themes.cpp b/src/ui/themes.cpp index 15b3bdb6..34964ce2 100644 --- a/src/ui/themes.cpp +++ b/src/ui/themes.cpp @@ -1,7 +1,10 @@ #include "themes.hpp" #include "core/lv_obj.h" +#include "core/lv_obj_tree.h" #include "esp_log.h" #include "misc/lv_color.h" +#include "misc/lv_style.h" +#include "widgets/lv_slider.h" LV_FONT_DECLARE(font_fusion); @@ -15,12 +18,17 @@ static void theme_apply_cb(lv_theme_t* th, lv_obj_t* obj) { Theme::Theme() { /*Initialize the styles*/ lv_style_init(&button_style_); - lv_style_set_pad_all(&button_style_, 2); + lv_style_set_pad_left(&button_style_, 2); + lv_style_set_pad_right(&button_style_, 2); + lv_style_set_pad_top(&button_style_, 1); + lv_style_set_pad_bottom(&button_style_, 1); lv_style_set_bg_color(&button_style_, lv_color_white()); + lv_style_set_radius(&button_style_, 5); lv_style_init(&button_style_focused_); lv_style_set_bg_color(&button_style_focused_, - lv_palette_lighten(LV_PALETTE_BLUE_GREY, 2)); + lv_palette_lighten(LV_PALETTE_BLUE, 5)); + lv_style_set_bg_opa(&button_style_focused_, LV_OPA_COVER); lv_theme_t* parent_theme = lv_disp_get_theme(NULL); theme_ = *parent_theme; @@ -38,28 +46,125 @@ void Theme::Apply(void) { void Theme::Callback(lv_obj_t* obj) { lv_obj_set_style_text_font(obj, &font_fusion, 0); lv_obj_set_style_text_color(obj, lv_color_black(), 0); + lv_obj_set_style_bg_opa(obj, LV_OPA_TRANSP, LV_PART_MAIN); + lv_obj_set_style_bg_color(obj, lv_palette_lighten(LV_PALETTE_BLUE, 5), + LV_PART_SELECTED | LV_STATE_CHECKED); if (lv_obj_check_type(obj, &lv_btn_class) || lv_obj_check_type(obj, &lv_list_btn_class)) { lv_obj_add_style(obj, &button_style_, LV_PART_MAIN); lv_obj_add_style(obj, &button_style_focused_, LV_PART_MAIN | LV_STATE_FOCUSED); - } + if (lv_obj_check_type(obj, &lv_list_btn_class)) { + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN); + } + } else if (lv_obj_check_type(obj, &lv_slider_class)) { + lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, LV_PART_MAIN); + + lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, LV_PART_INDICATOR); + lv_obj_set_style_bg_color(obj, lv_palette_main(LV_PALETTE_BLUE), + LV_PART_INDICATOR); + + lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, LV_PART_KNOB); + lv_obj_set_style_pad_all(obj, 2, LV_PART_KNOB); + lv_obj_set_style_bg_color(obj, lv_color_white(), LV_PART_KNOB); + lv_obj_set_style_bg_color(obj, lv_palette_lighten(LV_PALETTE_BLUE, 4), + LV_PART_KNOB | LV_STATE_FOCUSED); + lv_obj_set_style_shadow_width(obj, 5, LV_PART_KNOB); + lv_obj_set_style_shadow_opa(obj, LV_OPA_COVER, LV_PART_KNOB); + } else if (lv_obj_check_type(obj, &lv_switch_class)) { + lv_obj_set_size(obj, 28, 18); + lv_obj_set_style_pad_all(obj, -2, LV_PART_KNOB); + + lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, LV_PART_MAIN); + + lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, LV_PART_INDICATOR); + lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, LV_PART_INDICATOR); + lv_obj_set_style_bg_color(obj, lv_palette_main(LV_PALETTE_GREY), + LV_PART_INDICATOR); + lv_obj_set_style_bg_color(obj, lv_palette_main(LV_PALETTE_BLUE), + LV_PART_INDICATOR | LV_STATE_CHECKED); + + lv_obj_set_style_radius(obj, LV_RADIUS_CIRCLE, LV_PART_KNOB); + lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, LV_PART_KNOB); + lv_obj_set_style_bg_color(obj, lv_color_white(), LV_PART_KNOB); + lv_obj_set_style_bg_color(obj, lv_palette_lighten(LV_PALETTE_BLUE, 4), + LV_PART_KNOB | LV_STATE_FOCUSED); + } else if (lv_obj_check_type(obj, &lv_dropdown_class)) { + lv_obj_set_style_radius(obj, 2, LV_PART_MAIN); + lv_obj_set_style_pad_all(obj, 2, LV_PART_MAIN); + + lv_obj_set_style_border_width(obj, 1, LV_PART_MAIN); + lv_obj_set_style_border_color(obj, lv_palette_main(LV_PALETTE_BLUE), + LV_PART_MAIN); + lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_FULL, LV_PART_MAIN); - if (lv_obj_check_type(obj, &lv_switch_class)) { - lv_obj_set_style_border_width(obj, 1, LV_PART_MAIN | LV_STATE_FOCUSED); + lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_bg_color(obj, lv_palette_lighten(LV_PALETTE_BLUE, 5), + LV_PART_MAIN | LV_STATE_FOCUSED); } } void Theme::ApplyStyle(lv_obj_t* obj, Style style) { - if (style == Style::kTopBar) { - lv_obj_set_style_border_color( - obj, lv_palette_darken(LV_PALETTE_BLUE_GREY, 2), LV_PART_MAIN); - lv_obj_set_style_border_width(obj, 1, LV_PART_MAIN); - lv_obj_set_style_border_side( - obj, LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_TOP, LV_PART_MAIN); - lv_obj_set_style_pad_top(obj, 2, LV_PART_MAIN); - lv_obj_set_style_pad_bottom(obj, 2, LV_PART_MAIN); + switch (style) { + case Style::kTopBar: + lv_obj_set_style_pad_bottom(obj, 1, LV_PART_MAIN); + + lv_obj_set_style_shadow_width(obj, 6, LV_PART_MAIN); + lv_obj_set_style_shadow_opa(obj, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_shadow_ofs_x(obj, 0, LV_PART_MAIN); + break; + case Style::kPopup: + lv_obj_set_style_shadow_width(obj, 6, LV_PART_MAIN); + lv_obj_set_style_shadow_opa(obj, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_shadow_ofs_x(obj, 0, LV_PART_MAIN); + lv_obj_set_style_shadow_ofs_y(obj, 0, LV_PART_MAIN); + + lv_obj_set_style_radius(obj, 5, LV_PART_MAIN); + + lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, LV_PART_MAIN); + lv_obj_set_style_bg_color(obj, lv_color_white(), LV_PART_MAIN); + + lv_obj_set_style_pad_top(obj, 2, LV_PART_MAIN); + lv_obj_set_style_pad_bottom(obj, 2, LV_PART_MAIN); + lv_obj_set_style_pad_left(obj, 2, LV_PART_MAIN); + lv_obj_set_style_pad_right(obj, 2, LV_PART_MAIN); + break; + case Style::kTab: + lv_obj_set_style_radius(obj, 0, LV_PART_MAIN); + + lv_obj_set_style_border_width(obj, 1, LV_STATE_CHECKED); + lv_obj_set_style_border_color(obj, lv_palette_main(LV_PALETTE_BLUE), + LV_STATE_CHECKED); + lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_BOTTOM, + LV_STATE_CHECKED); + break; + case Style::kButtonPrimary: + lv_obj_set_style_border_width(obj, 1, LV_PART_MAIN); + lv_obj_set_style_border_color(obj, lv_palette_main(LV_PALETTE_BLUE), + LV_PART_MAIN); + lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_FULL, LV_PART_MAIN); + break; + case Style::kMenuSubheadFirst: + case Style::kMenuSubhead: + lv_obj_set_style_text_color(obj, lv_palette_darken(LV_PALETTE_GREY, 3), + LV_PART_MAIN); + lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); + + lv_obj_set_style_border_width(obj, 1, LV_PART_MAIN); + lv_obj_set_style_border_color(obj, lv_palette_lighten(LV_PALETTE_GREY, 3), + LV_PART_MAIN); + + if (style == Style::kMenuSubhead) { + lv_obj_set_style_border_side( + obj, LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN); + } else { + lv_obj_set_style_border_side(obj, LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN); + } + break; + default: + break; } } diff --git a/src/ui/widget_top_bar.cpp b/src/ui/widget_top_bar.cpp index 93cd32a4..d13df9db 100644 --- a/src/ui/widget_top_bar.cpp +++ b/src/ui/widget_top_bar.cpp @@ -60,9 +60,12 @@ TopBar::TopBar(lv_obj_t* parent, } lv_obj_t* title_ = lv_label_create(container_); - lv_label_set_text(title_, config.title.c_str()); + lv_obj_set_height(title_, 17); lv_obj_set_flex_grow(title_, 1); + lv_label_set_text(title_, config.title.c_str()); + lv_label_set_long_mode(title_, LV_LABEL_LONG_DOT); + lv_obj_t* playback = lv_img_create(container_); bindings_.push_back(model.is_playing.onChangedAndNow([=](bool is_playing) {