From c683e778730026d6769176a265fb45e65ee4f714 Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Thu, 24 Jun 2021 11:53:36 -0400 Subject: [PATCH] Implement TitlesTabPopup class. --- include/titles_tab.hpp | 31 ++++++++++++-- source/titles_tab.cpp | 94 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/include/titles_tab.hpp b/include/titles_tab.hpp index d2a55d5..5b92fa4 100644 --- a/include/titles_tab.hpp +++ b/include/titles_tab.hpp @@ -29,15 +29,40 @@ namespace nxdt::views { - /* Expanded ListItem class to hold a title ID. */ + /* Expanded TabFrame class used as a PopupFrame for titles. */ + class TitlesTabPopup: public brls::TabFrame + { + private: + const TitleApplicationMetadata *app_metadata = nullptr; + bool is_system = false; + + TitleUserApplicationData user_app_data = {0}; + TitleInfo *system_title_info = NULL; + + public: + TitlesTabPopup(const TitleApplicationMetadata *app_metadata, bool is_system); + ~TitlesTabPopup(void); + }; + + /* Expanded ListItem class to hold application metadata. */ class TitlesTabItem: public brls::ListItem { private: - u64 title_id = 0; + const TitleApplicationMetadata *app_metadata = nullptr; bool is_system = false; public: - TitlesTabItem(TitleApplicationMetadata *app_metadata, bool is_system); + TitlesTabItem(const TitleApplicationMetadata *app_metadata, bool is_system); + + ALWAYS_INLINE const TitleApplicationMetadata *GetApplicationMetadata(void) + { + return this->app_metadata; + } + + ALWAYS_INLINE bool IsSystemTitle(void) + { + return this->is_system; + } }; class TitlesTab: public LayeredErrorFrame diff --git a/source/titles_tab.cpp b/source/titles_tab.cpp index c693cee..a9a5876 100644 --- a/source/titles_tab.cpp +++ b/source/titles_tab.cpp @@ -21,23 +21,58 @@ #include #include +#include using namespace brls::i18n::literals; /* For _i18n. */ namespace nxdt::views { - TitlesTabItem::TitlesTabItem(TitleApplicationMetadata *app_metadata, bool is_system) : brls::ListItem(std::string(app_metadata->lang_entry.name), "", ""), \ - title_id(app_metadata->title_id), - is_system(is_system) + TitlesTabPopup::TitlesTabPopup(const TitleApplicationMetadata *app_metadata, bool is_system) : brls::TabFrame(), app_metadata(app_metadata), is_system(is_system) + { + u64 title_id = this->app_metadata->title_id; + bool user_ret = false; + + if (!this->is_system) + { + /* Get user application data. */ + user_ret = titleGetUserApplicationData(title_id, &(this->user_app_data)); + } else { + /* Get system title info. */ + this->system_title_info = titleGetInfoFromStorageByTitleId(NcmStorageId_BuiltInSystem, title_id); + } + + /* Make sure we got title information. */ + if ((!this->is_system && !user_ret) || (this->is_system && !this->system_title_info)) throw fmt::format("Failed to retrieve title information for {:016X}.", title_id); + + /* Add tabs. */ + this->addTab("Red", new brls::Rectangle(nvgRGB(255, 0, 0))); + this->addTab("Green", new brls::Rectangle(nvgRGB(0, 255, 0))); + this->addTab("Blue", new brls::Rectangle(nvgRGB(0, 0, 255))); + } + + TitlesTabPopup::~TitlesTabPopup(void) + { + /* Free title information. */ + if (!this->is_system) + { + titleFreeUserApplicationData(&(this->user_app_data)); + } else { + titleFreeTitleInfo(&(this->system_title_info)); + } + } + + TitlesTabItem::TitlesTabItem(const TitleApplicationMetadata *app_metadata, bool is_system) : brls::ListItem(std::string(app_metadata->lang_entry.name), "", ""), \ + app_metadata(app_metadata), + is_system(is_system) { brls::Style* style = brls::Application::getStyle(); /* Set sublabel. */ - this->subLabel = (!this->is_system ? std::string(app_metadata->lang_entry.author) : fmt::format("{:016X}", this->title_id)); + this->subLabel = (!this->is_system ? std::string(app_metadata->lang_entry.author) : fmt::format("{:016X}", this->app_metadata->title_id)); this->setHeight(style->List.Item.heightWithSubLabel); - /* Set thumbnail if we're dealing with user metadata. */ - if (!this->is_system && app_metadata->icon && app_metadata->icon_size) this->setThumbnail(app_metadata->icon, app_metadata->icon_size); + /* Set thumbnail (if needed). */ + if (app_metadata->icon && app_metadata->icon_size) this->setThumbnail(app_metadata->icon, app_metadata->icon_size); } TitlesTab::TitlesTab(nxdt::tasks::TitleTask *title_task, bool is_system) : LayeredErrorFrame("titles_tab/no_titles_available"_i18n), title_task(title_task), is_system(is_system) @@ -45,12 +80,13 @@ namespace nxdt::views /* Populate list. */ this->PopulateList(this->title_task->GetApplicationMetadata(this->is_system)); - /* Subscribe to title event if this is the user titles tab. */ + /* Subscribe to the title event if this is the user titles tab. */ if (!this->is_system) { this->title_task_sub = this->title_task->RegisterListener([this](const nxdt::tasks::TitleApplicationMetadataVector* app_metadata) { /* Update list. */ this->PopulateList(app_metadata); + brls::Application::notify("titles_tab/user_titles_notification"_i18n); }); } @@ -64,6 +100,10 @@ namespace nxdt::views void TitlesTab::PopulateList(const nxdt::tasks::TitleApplicationMetadataVector* app_metadata) { + /* Block inputs while we're doing our thing. */ + brls::Application::blockInputs(); + ON_SCOPE_EXIT { brls::Application::unblockInputs(); }; + if (!app_metadata) return; bool refocus = false; @@ -96,7 +136,45 @@ namespace nxdt::views if (!app_metadata_count) return; /* Populate list. */ - for(TitleApplicationMetadata *cur_app_metadata : *app_metadata) this->list->addView(new TitlesTabItem(cur_app_metadata, this->is_system)); + for(TitleApplicationMetadata *cur_app_metadata : *app_metadata) + { + /* Create list item. */ + TitlesTabItem *title = new TitlesTabItem(cur_app_metadata, this->is_system); + + /* Register click event. */ + title->getClickEvent()->subscribe([](brls::View *view){ + TitlesTabItem *item = static_cast(view); + const TitleApplicationMetadata *app_metadata = item->GetApplicationMetadata(); + bool is_system = item->IsSystemTitle(); + + /* Create popup. */ + TitlesTabPopup *popup = nullptr; + + try { + popup = new TitlesTabPopup(app_metadata, is_system); + } catch(const std::string& msg) { + brls::Logger::debug(msg); + if (popup) delete popup; + return; + } + + /* Display popup. */ + std::string name = std::string(app_metadata->lang_entry.name); + std::string tid = fmt::format("{:016X}", app_metadata->title_id); + std::string sub_left = (!is_system ? std::string(app_metadata->lang_entry.author) : tid); + std::string sub_right = (!is_system ? tid : ""); + + if (app_metadata->icon && app_metadata->icon_size) + { + brls::PopupFrame::open(name, app_metadata->icon, app_metadata->icon_size, popup, sub_left, sub_right); + } else { + brls::PopupFrame::open(name, popup, sub_left, sub_right); + } + }); + + /* Add list item to our view. */ + this->list->addView(title); + } /* Switch to the list. */ this->list->invalidate(true);