summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/include/modal_add_to_queue.hpp4
-rw-r--r--src/ui/include/themes.hpp11
-rw-r--r--src/ui/modal.cpp3
-rw-r--r--src/ui/modal_add_to_queue.cpp125
-rw-r--r--src/ui/screen.cpp2
-rw-r--r--src/ui/screen_menu.cpp1
-rw-r--r--src/ui/screen_playing.cpp29
-rw-r--r--src/ui/screen_settings.cpp69
-rw-r--r--src/ui/themes.cpp131
-rw-r--r--src/ui/widget_top_bar.cpp5
10 files changed, 308 insertions, 72 deletions
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<playlist::IndexRecordSource> 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<playlist::IndexRecordSource> 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<uint16_t>(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) {