- Added "dimensions" support to Locale

- Added support for a "album header" play queue overlay
- Removed some code in Window that was causing unnecessary visibility
  changed callbacks
- Added Window::OnAddedToParent and Window::OnRemovedFromParent
- Updated themes to support "list_header_highlighted_background" and
  "list_header_highlighted_foreground"
This commit is contained in:
casey langen 2017-03-21 16:53:10 -07:00
parent a37702f5da
commit f7a4ecdf2e
17 changed files with 203 additions and 46 deletions

View File

@ -41,14 +41,16 @@
#include "Locale.h"
#define KEY_STRINGS "strings"
#define KEY_DIMENSIONS "dimensions"
#define DEFAULT_LOCALE "en_US"
using namespace musik::core::i18n;
using namespace musik::core;
using namespace musik::core::prefs;
using namespace boost::filesystem;
static nlohmann::json empty;
static nlohmann::json loadLocaleData(const std::string& fn) {
char* bytes = nullptr;
int count = 0;
@ -142,13 +144,10 @@ std::string Locale::Translate(const std::string& key) {
}
std::string Locale::Translate(const char* key) {
static nlohmann::json empty;
/* get the string from the current locale */
if (!this->localeData.is_null()) {
const nlohmann::json& strings = this->localeData.value(KEY_STRINGS, empty);
auto it = strings.find(key);
if (it != strings.end()) {
return it.value();
}
@ -163,4 +162,22 @@ std::string Locale::Translate(const char* key) {
/* otherwise, just return the key! */
return key;
}
int Locale::Dimension(const char* key, int defaultValue) {
if (!this->localeData.is_null()) { /* current locale */
const nlohmann::json& strings = this->localeData.value(KEY_DIMENSIONS, empty);
auto it = strings.find(key);
if (it != strings.end()) {
return it.value();
}
}
if (!this->defaultLocaleData.is_null()) { /* fall back to default */
const nlohmann::json& strings = this->defaultLocaleData.value(KEY_DIMENSIONS, empty);
auto it = strings.find(key);
return (it != strings.end()) ? it.value() : key;
}
return defaultValue; /* not found anywhere */
}

View File

@ -62,6 +62,8 @@ namespace musik { namespace core { namespace i18n {
std::string Translate(const std::string& key);
std::string Translate(const char* key);
int Dimension(const char* key, int defaultValue);
private:
Locale();
@ -75,6 +77,7 @@ namespace musik { namespace core { namespace i18n {
#define _TSTR(KEY) (musik::core::i18n::Locale::Instance().Translate(KEY))
#define _TCP(KEY) (musik::core::i18n::Locale::Instance().Translate(KEY).c_str())
#define _DIMEN(KEY, DEFAULT) (musik::core::i18n::Locale::Instance().Dimension(KEY, DEFAULT))
} } }

View File

@ -45,7 +45,7 @@ namespace musik {
virtual ~IMessageQueue() { }
virtual void Post(IMessagePtr message, int64 delayMs = 0) = 0;
virtual int Remove(IMessageTarget *target, int type = -1) = 0;
virtual void Broadcast(IMessagePtr message, int64 delayMs) = 0;
virtual void Broadcast(IMessagePtr message, int64 delayMs = 0) = 0;
virtual bool Contains(IMessageTarget *target, int type = -1) = 0;
virtual void Debounce(IMessagePtr message, int64 delayMs = 0) = 0;
virtual void RegisterForBroadcasts(IMessageTargetPtr target) = 0;

View File

@ -49,8 +49,8 @@ namespace musik { namespace core { namespace runtime {
static IMessagePtr Create(
IMessageTarget* target,
int messageType,
int64 data1,
int64 data2);
int64 data1 = 0LL,
int64 data2 = 0LL);
virtual ~Message() {
}

View File

@ -49,7 +49,7 @@ namespace musik { namespace core { namespace runtime {
virtual ~MessageQueue();
virtual void Post(IMessagePtr message, int64 delayMs = 0);
virtual void Broadcast(IMessagePtr message, int64 messageMs);
virtual void Broadcast(IMessagePtr message, int64 messageMs = 0);
virtual int Remove(IMessageTarget *target, int type = -1);
virtual bool Contains(IMessageTarget *target, int type = -1);
virtual void Debounce(IMessagePtr message, int64 delayMs = 0);

View File

@ -56,6 +56,8 @@ using namespace cursespp;
static size_t MAX_CATEGORY_WIDTH = 40;
static int MIN_LIST_TITLE_HEIGHT = 26;
#define MESSAGE_INDEXER_PROGRESS 2033
#define DEFAULT_CATEGORY constants::Track::ARTIST
#define DEFAULT_CATEGORY_NAME FIELD_TO_TITLE[DEFAULT_CATEGORY]
@ -137,6 +139,14 @@ void BrowseLayout::InitializeWindows() {
this, &BrowseLayout::OnCategoryViewInvalidated);
}
void BrowseLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
if (message.Type() == MESSAGE_INDEXER_PROGRESS) {
this->categoryList->Requery();
}
LayoutBase::ProcessMessage(message);
}
void BrowseLayout::ScrollTo(const std::string& fieldType, DBID fieldId) {
this->SetFocus(this->trackList);
this->categoryList->RequeryWithField(fieldType, "", fieldId);
@ -153,12 +163,13 @@ void BrowseLayout::OnVisibilityChanged(bool visible) {
LayoutBase::OnVisibilityChanged(visible);
if (visible) {
Window::MessageQueue().RegisterForBroadcasts(shared_from_this());
this->categoryList->Requery();
}
}
void BrowseLayout::OnIndexerProgress(int count) {
this->categoryList->Requery();
this->PostMessage(MESSAGE_INDEXER_PROGRESS);
}
void BrowseLayout::RequeryTrackList(ListWindow *view) {

View File

@ -65,7 +65,7 @@ namespace musik {
virtual void OnVisibilityChanged(bool visible);
virtual cursespp::IWindowPtr GetFocus();
virtual bool KeyPress(const std::string& key);
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
void ScrollTo(const std::string& fieldType, DBID fieldId);
protected:

View File

@ -39,6 +39,7 @@
#include <core/library/LocalLibraryConstants.h>
#include <app/overlay/PlayQueueOverlays.h>
#include <app/util/Hotkeys.h>
#include <glue/util/Playback.h>
@ -146,6 +147,7 @@ void LibraryLayout::ShowTrackSearch() {
void LibraryLayout::InitializeWindows() {
this->browseLayout.reset(new BrowseLayout(this->playback, this->library));
this->nowPlayingLayout.reset(new NowPlayingLayout(this->playback, this->library));
this->searchLayout.reset(new SearchLayout(this->playback, this->library));
@ -194,6 +196,14 @@ void LibraryLayout::UpdateShortcutsWindow() {
}
}
void LibraryLayout::OnAddedToParent(IWindow* parent) {
MessageQueue().RegisterForBroadcasts(shared_from_this());
}
void LibraryLayout::OnRemovedFromParent(IWindow* parent) {
MessageQueue().UnregisterForBroadcasts(shared_from_this());
}
void LibraryLayout::OnSearchResultSelected(
SearchLayout* layout, std::string fieldType, DBID fieldId)
{
@ -255,6 +265,14 @@ bool LibraryLayout::SetFocus(cursespp::IWindowPtr window) {
return this->visibleLayout->SetFocus(window);
}
void LibraryLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
if (message.Type() == PlayQueueOverlays::BROADCAST_JUMP_TO_ALBUM) {
this->OnSearchResultSelected(nullptr, constants::Track::ALBUM, message.UserData1());
}
LayoutBase::ProcessMessage(message);
}
bool LibraryLayout::KeyPress(const std::string& key) {
if (key == "^[") { /* switches between browse/now playing */
if (this->visibleLayout != this->browseLayout) {

View File

@ -68,6 +68,7 @@ namespace musik {
virtual cursespp::IWindowPtr FocusPrev();
virtual cursespp::IWindowPtr GetFocus();
virtual bool SetFocus(cursespp::IWindowPtr window);
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
virtual void SetShortcutsWindow(
cursespp::ShortcutsWindow* w);
@ -76,6 +77,8 @@ namespace musik {
protected:
virtual void OnLayout();
virtual void OnAddedToParent(IWindow* newParent);
virtual void OnRemovedFromParent(IWindow* oldParent);
private:
void OnSearchResultSelected(

View File

@ -44,6 +44,7 @@
#include <core/library/query/local/GetPlaylistQuery.h>
#include <core/library/query/local/SavePlaylistQuery.h>
#include <core/library/query/local/DeletePlaylistQuery.h>
#include <core/runtime/Message.h>
#include <cursespp/App.h>
#include <cursespp/SimpleScrollAdapter.h>
@ -114,7 +115,7 @@ static void showPlaylistListOverlay(
dialog->SetAdapter(adapter)
.SetTitle(title)
.SetWidth(DEFAULT_OVERLAY_WIDTH)
.SetWidth(_DIMEN("playqueue_playlist_list_overlay", DEFAULT_OVERLAY_WIDTH))
.SetSelectedIndex(selectedIndex)
.SetItemSelectedCallback(callback);
@ -153,7 +154,7 @@ static void createNewPlaylist(
std::shared_ptr<InputOverlay> dialog(new InputOverlay());
dialog->SetTitle(_TSTR("playqueue_overlay_playlist_name_title"))
.SetWidth(DEFAULT_OVERLAY_WIDTH)
.SetWidth(_DIMEN("playqueue_playlist_name_overlay", DEFAULT_OVERLAY_WIDTH))
.SetText("")
.SetInputAcceptedCallback(
[tracks, library](const std::string& name) {
@ -173,7 +174,7 @@ static void renamePlaylist(
std::shared_ptr<InputOverlay> dialog(new InputOverlay());
dialog->SetTitle(_TSTR("playqueue_overlay_new_playlist_name_title"))
.SetWidth(DEFAULT_OVERLAY_WIDTH)
.SetWidth(_DIMEN("playqueue_playlist_name_overlay", DEFAULT_OVERLAY_WIDTH))
.SetText(oldName)
.SetInputAcceptedCallback(
[library, playlistId](const std::string& name) {
@ -221,6 +222,36 @@ static void showNoPlaylistsDialog() {
App::Overlays().Push(dialog);
}
static void handleAddCategorySelection(
musik::core::audio::PlaybackService& playback,
musik::core::ILibraryPtr library,
const std::string& fieldColumn,
DBID fieldId,
size_t type)
{
std::shared_ptr<CategoryTrackListQuery> query(
new CategoryTrackListQuery(library, fieldColumn, fieldId));
library->Enqueue(query, ILibrary::QuerySynchronous);
if (query->GetStatus() == IQuery::Finished) {
auto editor = playback.Edit();
auto tracks = query->GetResult();
size_t position = playback.GetIndex();
if (type == 0 || position == ListWindow::NO_SELECTION) { /* end */
for (size_t i = 0; i < tracks->Count(); i++) {
editor.Add(tracks->GetId(i));
}
}
else { /* after next */
for (size_t i = 0; i < tracks->Count(); i++) {
editor.Insert(tracks->GetId(i), position + 1 + i);
}
}
}
}
PlayQueueOverlays::PlayQueueOverlays() {
}
@ -234,8 +265,8 @@ void PlayQueueOverlays::ShowAddTrackOverlay(
dialog->SetAdapter(adapter)
.SetTitle(_TSTR("playqueue_overlay_add_to_queue_title"))
.SetWidth(_DIMEN("playqueue_playlist_add_to_queue_overlay", DEFAULT_OVERLAY_WIDTH))
.SetSelectedIndex(0)
.SetWidth(DEFAULT_OVERLAY_WIDTH)
.SetItemSelectedCallback(
[trackId, &playback](ListOverlay* overlay, IScrollAdapterPtr adapter, size_t index) {
auto editor = playback.Edit();
@ -268,8 +299,8 @@ void PlayQueueOverlays::ShowAddCategoryOverlay(
dialog->SetAdapter(adapter)
.SetTitle(_TSTR("playqueue_overlay_add_to_queue_title"))
.SetWidth(_DIMEN("playqueue_playlist_add_to_queue_overlay", DEFAULT_OVERLAY_WIDTH))
.SetSelectedIndex(0)
.SetWidth(DEFAULT_OVERLAY_WIDTH)
.SetItemSelectedCallback(
[&playback, library, fieldColumn, fieldId]
(ListOverlay* overlay, IScrollAdapterPtr adapter, size_t index) {
@ -277,35 +308,52 @@ void PlayQueueOverlays::ShowAddCategoryOverlay(
return;
}
std::shared_ptr<CategoryTrackListQuery>
query(new CategoryTrackListQuery(
library,
fieldColumn,
fieldId));
library->Enqueue(query, ILibrary::QuerySynchronous);
if (query->GetStatus() == IQuery::Finished) {
auto editor = playback.Edit();
auto tracks = query->GetResult();
size_t position = playback.GetIndex();
if (index == 0 || position == ListWindow::NO_SELECTION) { /* end */
for (size_t i = 0; i < tracks->Count(); i++) {
editor.Add(tracks->GetId(i));
}
}
else { /* after next */
for (size_t i = 0; i < tracks->Count(); i++) {
editor.Insert(tracks->GetId(i), position + 1 + i);
}
}
}
handleAddCategorySelection(playback, library, fieldColumn, fieldId, index);
});
cursespp::App::Overlays().Push(dialog);
}
void PlayQueueOverlays::ShowAlbumDividerOverlay(
musik::core::runtime::IMessageQueue& messageQueue,
musik::core::audio::PlaybackService& playback,
musik::core::ILibraryPtr library,
musik::core::TrackPtr firstTrack)
{
std::shared_ptr<Adapter> adapter(new Adapter());
adapter->AddEntry(_TSTR("playqueue_overlay_album_jump_to"));
adapter->AddEntry(_TSTR("playqueue_overlay_add_to_end_in_queue"));
adapter->AddEntry(_TSTR("playqueue_overlay_add_as_next_in_queue"));
adapter->SetSelectable(true);
std::shared_ptr<ListOverlay> dialog(new ListOverlay());
dialog->SetAdapter(adapter)
.SetTitle(_TSTR("playqueue_overlay_album_header"))
.SetWidth(_DIMEN("playqueue_album_header_overlay", DEFAULT_OVERLAY_WIDTH))
.SetSelectedIndex(0)
.SetItemSelectedCallback(
[&playback, library, &messageQueue, firstTrack]
(ListOverlay* overlay, IScrollAdapterPtr adapter, size_t index) {
if (index == ListWindow::NO_SELECTION) {
return;
}
auto albumColumn = library::constants::Track::ALBUM_ID;
auto albumId = firstTrack->GetUint64(albumColumn);
if (index == 0) {
messageQueue.Broadcast(runtime::Message::Create(
nullptr, PlayQueueOverlays::BROADCAST_JUMP_TO_ALBUM, albumId));
}
else {
handleAddCategorySelection(playback, library, albumColumn, albumId, index - 1);
}
});
cursespp::App::Overlays().Push(dialog);
}
void PlayQueueOverlays::ShowLoadPlaylistOverlay(
musik::core::audio::PlaybackService& playback,
musik::core::ILibraryPtr library,

View File

@ -43,6 +43,8 @@ namespace musik {
namespace box {
class PlayQueueOverlays {
public:
static const int BROADCAST_JUMP_TO_ALBUM = 3000;
using PlaylistSelectedCallback = std::function<void(DBID)>;
static void ShowAddTrackOverlay(
@ -55,6 +57,12 @@ namespace musik {
const std::string& fieldColumn,
DBID fieldId);
static void ShowAlbumDividerOverlay(
musik::core::runtime::IMessageQueue& messageQueue,
musik::core::audio::PlaybackService& playback,
musik::core::ILibraryPtr library,
musik::core::TrackPtr firstTrack);
static void ShowLoadPlaylistOverlay(
musik::core::audio::PlaybackService& playback,
musik::core::ILibraryPtr library,

View File

@ -202,11 +202,14 @@ bool TrackListView::KeyPress(const std::string& key) {
if (headers.HeaderAt(this->GetSelectedIndex())) {
auto track = this->GetSelectedTrack();
PlayQueueOverlays::ShowAddCategoryOverlay(
this->playback,
this->library,
constants::Track::ALBUM,
track->GetUint64(constants::Track::ALBUM_ID));
PlayQueueOverlays::ShowAlbumDividerOverlay(
MessageQueue(), this->playback, this->library, track);
//PlayQueueOverlays::ShowAddCategoryOverlay(
// this->playback,
// this->library,
// constants::Track::ALBUM,
// track->GetUint64(constants::Track::ALBUM_ID));
handled = true;
}

View File

@ -203,12 +203,20 @@ void Window::SetParent(IWindow* parent) {
if (this->parent != parent) {
IWindowGroup* group = dynamic_cast<IWindowGroup*>(this->parent);
IWindow* oldParent = this->parent;
this->parent = parent;
if (this->frame) {
this->Hide();
this->Show();
}
if (parent) {
this->OnAddedToParent(parent);
}
else {
this->OnRemovedFromParent(oldParent);
}
}
}
@ -283,6 +291,14 @@ void Window::OnRedraw() {
/* for subclass use */
}
void Window::OnAddedToParent(IWindow* newParent) {
/* for subclass use */
}
void Window::OnRemovedFromParent(IWindow* oldParent) {
/* for subclass use */
}
void Window::Redraw() {
this->isDirty = true;
@ -450,7 +466,7 @@ void Window::OnParentVisibilityChanged(bool visible) {
this->Destroy();
}
this->OnVisibilityChanged(false);
//this->OnVisibilityChanged(false);
}
else if (visible && this->isVisible) {
if (this->framePanel) {
@ -460,7 +476,7 @@ void Window::OnParentVisibilityChanged(bool visible) {
this->Recreate();
}
this->OnVisibilityChanged(true);
//this->OnVisibilityChanged(true);
}
}

View File

@ -138,6 +138,8 @@ namespace cursespp {
virtual void OnVisibilityChanged(bool visible);
virtual void OnFocusChanged(bool focused);
virtual void OnRedraw();
virtual void OnAddedToParent(IWindow* newParent);
virtual void OnRemovedFromParent(IWindow* oldParent);
private:
IWindow* parent;

View File

@ -57,6 +57,11 @@
"playqueue_overlay_new_playlist_name_title": "new playlist name",
"playqueue_overlay_confirm_delete_message": "are you sure you want to delete '%s'?",
"playqueue_overlay_load_playlists_none_message": "you haven't saved any playlists yet!",
"playqueue_overlay_album_header": "album actions",
"playqueue_overlay_album_jump_to": "jump to album in library",
"playqueue_overlay_add_to_end_in_queue": "add to end of play queue",
"playqueue_overlay_add_as_next_in_queue": "add as next in play queue",
"visualizer_overlay_title": "visualizers",
"visualizer_overlay_no_visualizers_message": "no visualizers found!",
@ -85,5 +90,12 @@
"transport_repeat_off": "repeat off",
"main_syncing_banner": "syncing metadata (%d tracks processed)"
},
"dimensions": {
"playqueue_album_header_overlay": 35,
"playqueue_playlist_add_to_queue_overlay": 30,
"playqueue_playlist_list_overlay": 30,
"playqueue_playlist_name_overlay": 30
}
}

View File

@ -101,6 +101,14 @@
"list_header_foreground": {
"hex": "#859900",
"palette": 64
},
"list_header_highlighted_background": {
"hex": "#859900",
"palette": 64
},
"list_header_highlighted_foreground": {
"hex": "#002b36",
"palette": 234
},
"list_item_highlighted_background": {
"hex": "#93a1a1",

View File

@ -102,6 +102,14 @@
"hex": "#859900",
"palette": 64
},
"list_header_highlighted_background": {
"hex": "#859900",
"palette": 64
},
"list_header_highlighted_foreground": {
"hex": "#fdf6e3",
"palette": 230
},
"list_item_highlighted_background": {
"hex": "#93a1a1",
"palette": 245