Make title bar a common component, some ui nits
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
idf_component_register(
|
||||
SRCS "lvgl_task.cpp" "ui_fsm.cpp" "screen_splash.cpp" "screen_menu.cpp" "wheel_encoder.cpp" "screen_track_browser.cpp" "screen_playing.cpp" "themes.cpp"
|
||||
"widget_top_bar.cpp"
|
||||
"splash.c" "font_fusion.c" "font_symbols.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer")
|
||||
|
||||
@@ -49,6 +49,7 @@ class TrackBrowser : public Screen {
|
||||
-> std::optional<database::IndexRecord>;
|
||||
|
||||
std::weak_ptr<database::Database> db_;
|
||||
lv_obj_t* back_button_;
|
||||
lv_obj_t* list_;
|
||||
lv_obj_t* loading_indicator_;
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ struct IndexSelected : tinyfsm::Event {
|
||||
database::IndexInfo index;
|
||||
};
|
||||
|
||||
struct BackPressed : tinyfsm::Event {};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace ui
|
||||
|
||||
@@ -48,6 +48,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
|
||||
|
||||
virtual void react(const internal::RecordSelected&) {}
|
||||
virtual void react(const internal::IndexSelected&) {}
|
||||
virtual void react(const internal::BackPressed&) {}
|
||||
|
||||
virtual void react(const system_fsm::DisplayReady&) {}
|
||||
virtual void react(const system_fsm::BootComplete&) {}
|
||||
@@ -83,6 +84,7 @@ class Browse : public UiState {
|
||||
|
||||
void react(const internal::RecordSelected&) override;
|
||||
void react(const internal::IndexSelected&) override;
|
||||
void react(const internal::BackPressed&) override;
|
||||
|
||||
void react(const system_fsm::KeyLockChanged&) override;
|
||||
void react(const system_fsm::StorageMounted&) override;
|
||||
@@ -93,6 +95,8 @@ class Playing : public UiState {
|
||||
void entry() override;
|
||||
void exit() override;
|
||||
|
||||
void react(const internal::BackPressed&) override;
|
||||
|
||||
void react(const audio::PlaybackStarted&) override;
|
||||
void react(const audio::PlaybackUpdate&) override;
|
||||
void react(const audio::QueueUpdate&) override;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
namespace widgets {
|
||||
|
||||
class TopBar {
|
||||
public:
|
||||
TopBar(lv_obj_t* parent, lv_group_t* group);
|
||||
|
||||
auto set_title(const std::string&) -> void;
|
||||
|
||||
lv_obj_t* container_;
|
||||
lv_obj_t* title_;
|
||||
lv_obj_t* back_button_;
|
||||
};
|
||||
|
||||
} // namespace widgets
|
||||
|
||||
} // namespace ui
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "track.hpp"
|
||||
#include "ui_events.hpp"
|
||||
#include "ui_fsm.hpp"
|
||||
#include "widget_top_bar.hpp"
|
||||
#include "widgets/lv_btn.h"
|
||||
#include "widgets/lv_img.h"
|
||||
#include "widgets/lv_label.h"
|
||||
@@ -114,6 +115,8 @@ Playing::Playing(std::weak_ptr<database::Database> db, audio::TrackQueue* queue)
|
||||
lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START,
|
||||
LV_FLEX_ALIGN_START);
|
||||
|
||||
lv_obj_set_scrollbar_mode(root_, LV_SCROLLBAR_MODE_OFF);
|
||||
|
||||
lv_obj_t* above_fold_container = lv_obj_create(root_);
|
||||
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));
|
||||
@@ -121,11 +124,8 @@ Playing::Playing(std::weak_ptr<database::Database> db, audio::TrackQueue* queue)
|
||||
lv_obj_set_flex_align(above_fold_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
|
||||
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
|
||||
|
||||
lv_obj_t* back_button = lv_btn_create(above_fold_container);
|
||||
lv_obj_set_size(back_button, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_obj_t* back_label = lv_label_create(back_button);
|
||||
lv_label_set_text(back_label, "<");
|
||||
lv_group_add_obj(group_, back_button);
|
||||
widgets::TopBar top_bar(above_fold_container, group_);
|
||||
top_bar.set_title("Now Playing");
|
||||
|
||||
lv_obj_t* info_container = lv_obj_create(above_fold_container);
|
||||
lv_obj_set_layout(info_container, LV_LAYOUT_FLEX);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "screen_track_browser.hpp"
|
||||
#include "ui_events.hpp"
|
||||
#include "ui_fsm.hpp"
|
||||
#include "widget_top_bar.hpp"
|
||||
#include "widgets/lv_label.h"
|
||||
|
||||
static constexpr char kTag[] = "browser";
|
||||
@@ -70,29 +71,17 @@ TrackBrowser::TrackBrowser(
|
||||
lv_obj_set_layout(root_, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_size(root_, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_flex_flow(root_, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START,
|
||||
LV_FLEX_ALIGN_START);
|
||||
lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER,
|
||||
LV_FLEX_ALIGN_CENTER);
|
||||
|
||||
// The default scrollbar is deceptive because we load in items progressively.
|
||||
lv_obj_set_scrollbar_mode(root_, LV_SCROLLBAR_MODE_OFF);
|
||||
// Wrapping behaves in surprising ways, again due to progressing loading.
|
||||
lv_group_set_wrap(group_, false);
|
||||
|
||||
lv_obj_t* header = lv_obj_create(root_);
|
||||
lv_obj_set_size(header, lv_pct(100), 15);
|
||||
lv_obj_set_flex_flow(header, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START,
|
||||
LV_FLEX_ALIGN_CENTER);
|
||||
|
||||
lv_obj_t* title_label = lv_label_create(header);
|
||||
lv_label_set_text(title_label, title.c_str());
|
||||
lv_obj_set_flex_grow(title_label, 1);
|
||||
|
||||
lv_obj_t* playback_label = lv_label_create(header);
|
||||
lv_label_set_text(playback_label, LV_SYMBOL_PAUSE);
|
||||
|
||||
lv_obj_t* battery_label = lv_label_create(header);
|
||||
lv_label_set_text(battery_label, LV_SYMBOL_BATTERY_2);
|
||||
widgets::TopBar top_bar(root_, group_);
|
||||
top_bar.set_title(title);
|
||||
back_button_ = top_bar.back_button_;
|
||||
|
||||
list_ = lv_list_create(root_);
|
||||
lv_obj_set_width(list_, lv_pct(100));
|
||||
@@ -209,6 +198,7 @@ auto TrackBrowser::AddResults(Position pos,
|
||||
}
|
||||
|
||||
lv_group_remove_all_objs(group_);
|
||||
lv_group_add_obj(group_, back_button_);
|
||||
int num_children = lv_obj_get_child_cnt(list_);
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
lv_group_add_obj(group_, lv_obj_get_child(list_, i));
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "system_events.hpp"
|
||||
#include "touchwheel.hpp"
|
||||
#include "track_queue.hpp"
|
||||
#include "ui_events.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@@ -147,6 +148,10 @@ void Browse::react(const internal::IndexSelected& ev) {
|
||||
std::move(query)));
|
||||
}
|
||||
|
||||
void Browse::react(const internal::BackPressed& ev) {
|
||||
PopScreen();
|
||||
}
|
||||
|
||||
static std::shared_ptr<screens::Playing> sPlayingScreen;
|
||||
|
||||
void Playing::entry() {
|
||||
@@ -171,6 +176,10 @@ void Playing::react(const audio::QueueUpdate& ev) {
|
||||
sPlayingScreen->OnQueueUpdate();
|
||||
}
|
||||
|
||||
void Playing::react(const internal::BackPressed& ev) {
|
||||
transit<Browse>();
|
||||
}
|
||||
|
||||
} // namespace states
|
||||
} // namespace ui
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#include "widget_top_bar.hpp"
|
||||
#include "core/lv_group.h"
|
||||
#include "core/lv_obj.h"
|
||||
#include "event_queue.hpp"
|
||||
#include "extra/layouts/flex/lv_flex.h"
|
||||
#include "ui_events.hpp"
|
||||
#include "ui_fsm.hpp"
|
||||
#include "widgets/lv_img.h"
|
||||
|
||||
namespace ui {
|
||||
namespace widgets {
|
||||
|
||||
static void back_click_cb(lv_event_t* ev) {
|
||||
events::Dispatch<internal::BackPressed, UiState>({});
|
||||
}
|
||||
|
||||
TopBar::TopBar(lv_obj_t* parent, lv_group_t* group) {
|
||||
container_ = lv_obj_create(parent);
|
||||
lv_obj_set_size(container_, lv_pct(100), 14);
|
||||
lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(container_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START,
|
||||
LV_FLEX_ALIGN_END);
|
||||
|
||||
back_button_ = lv_btn_create(container_);
|
||||
lv_obj_set_size(back_button_, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_obj_t* button_icon = lv_label_create(back_button_);
|
||||
lv_label_set_text(button_icon, "<");
|
||||
|
||||
lv_group_add_obj(group, back_button_);
|
||||
lv_obj_add_event_cb(back_button_, back_click_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
title_ = lv_label_create(container_);
|
||||
lv_label_set_text(title_, "");
|
||||
lv_obj_set_flex_grow(title_, 1);
|
||||
|
||||
lv_obj_t* playback_label = lv_label_create(container_);
|
||||
lv_label_set_text(playback_label, LV_SYMBOL_PAUSE);
|
||||
|
||||
lv_obj_t* battery_label = lv_label_create(container_);
|
||||
lv_label_set_text(battery_label, LV_SYMBOL_BATTERY_2);
|
||||
}
|
||||
|
||||
auto TopBar::set_title(const std::string& new_title) -> void {
|
||||
lv_label_set_text(title_, new_title.c_str());
|
||||
}
|
||||
|
||||
} // namespace widgets
|
||||
} // namespace ui
|
||||
Reference in New Issue
Block a user