1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-22 18:26:39 +00:00

Implemented UserTitlesTab class.

* LayeredErrorFrame: both the error frame and the list are now protected instead of private, letting any expanded classes take more control over the them. SetErrorFrameMessage(), AddListView() and the class destructor have been removed because of this change.

* LayeredErrorFrame: removed views vector and simplified the list element focus check carried out before switching to the error frame.
This commit is contained in:
Pablo Curiel 2021-06-20 22:43:40 -04:00
parent 1a2289c396
commit 65a7816f2e
8 changed files with 189 additions and 65 deletions

View file

@ -32,7 +32,7 @@ namespace nxdt::views
{
class GameCardTab: public LayeredErrorFrame
{
typedef bool (*GameCardSizeFunc)(u64 *size);
typedef bool (*GameCardSizeFunc)(u64 *out_size);
private:
nxdt::tasks::GameCardTask *gc_status_task = nullptr;

View file

@ -31,22 +31,14 @@ namespace nxdt::views
/* Extended class to switch between ErrorFrame and List views on demand. */
class LayeredErrorFrame: public brls::LayerView
{
private:
int layer_view_index = 0;
ErrorFrame *error_frame = nullptr;
brls::List *list = nullptr;
std::vector<brls::View*> list_views;
protected:
ErrorFrame *error_frame = nullptr;
brls::List *list = nullptr;
void SwitchLayerView(bool use_error_frame);
void SetErrorFrameMessage(std::string msg = "");
void AddListView(brls::View* view);
public:
LayeredErrorFrame(void);
~LayeredErrorFrame(void);
LayeredErrorFrame(std::string msg = "");
};
}

View file

@ -0,0 +1,47 @@
/*
* user_titles_tab.hpp
*
* Copyright (c) 2020-2021, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
*
* nxdumptool is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* nxdumptool is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __USER_TITLES_TAB_HPP__
#define __USER_TITLES_TAB_HPP__
#include "tasks.hpp"
#include "layered_error_frame.hpp"
namespace nxdt::views
{
class UserTitlesTab: public LayeredErrorFrame
{
private:
nxdt::tasks::TitleTask *title_task = nullptr;
nxdt::tasks::VoidEvent::Subscription title_task_sub;
nxdt::tasks::TitleApplicationMetadataVector *user_app_metadata = nullptr;
void PopulateList(void);
public:
UserTitlesTab(nxdt::tasks::TitleTask *title_task);
~UserTitlesTab(void);
};
}
#endif /* __USER_TITLES_TAB_HPP__ */

View file

@ -0,0 +1,5 @@
{
"error_frame": {
"no_titles_available": "No user titles available."
}
}

View file

@ -41,13 +41,14 @@ namespace nxdt::views
[GameCardCompatibilityType_Terra] = "Terra"
};
GameCardTab::GameCardTab(nxdt::tasks::GameCardTask *gc_status_task) : LayeredErrorFrame(), gc_status_task(gc_status_task)
GameCardTab::GameCardTab(nxdt::tasks::GameCardTask *gc_status_task) : LayeredErrorFrame("gamecard_tab/error_frame/not_inserted"_i18n), gc_status_task(gc_status_task)
{
/* Error frame. */
this->SetErrorFrameMessage("gamecard_tab/error_frame/not_inserted"_i18n);
/* Set custom spacing. */
this->list->setSpacing(this->list->getSpacing() / 2);
this->list->setMarginBottom(20);
/* Gamecard properties table. */
this->AddListView(new brls::Header("gamecard_tab/list/properties_table/header"_i18n));
this->list->addView(new brls::Header("gamecard_tab/list/properties_table/header"_i18n));
this->properties_table = new FocusableTable(false);
this->capacity = this->properties_table->addRow(brls::TableRowType::BODY, "gamecard_tab/list/properties_table/capacity"_i18n);
@ -57,28 +58,28 @@ namespace nxdt::views
this->lafw_version = this->properties_table->addRow(brls::TableRowType::BODY, "gamecard_tab/list/properties_table/lafw_version"_i18n);
this->sdk_version = this->properties_table->addRow(brls::TableRowType::BODY, "gamecard_tab/list/properties_table/sdk_version"_i18n);
this->compatibility_type = this->properties_table->addRow(brls::TableRowType::BODY, "gamecard_tab/list/properties_table/compatibility_type"_i18n);
this->AddListView(this->properties_table);
this->list->addView(this->properties_table);
/* ListItem elements. */
this->AddListView(new brls::Header("gamecard_tab/list/dump_options"_i18n));
this->list->addView(new brls::Header("gamecard_tab/list/dump_options"_i18n));
this->dump_card_image = new brls::ListItem("gamecard_tab/list/dump_card_image/label"_i18n, "gamecard_tab/list/dump_card_image/description"_i18n);
this->AddListView(this->dump_card_image);
this->list->addView(this->dump_card_image);
this->dump_certificate = new brls::ListItem("gamecard_tab/list/dump_certificate/label"_i18n, "gamecard_tab/list/dump_certificate/description"_i18n);
this->AddListView(this->dump_certificate);
this->list->addView(this->dump_certificate);
this->dump_header = new brls::ListItem("gamecard_tab/list/dump_header/label"_i18n, "gamecard_tab/list/dump_header/description"_i18n);
this->AddListView(this->dump_header);
this->list->addView(this->dump_header);
this->dump_decrypted_cardinfo = new brls::ListItem("gamecard_tab/list/dump_decrypted_cardinfo/label"_i18n, "gamecard_tab/list/dump_decrypted_cardinfo/description"_i18n);
this->AddListView(this->dump_decrypted_cardinfo);
this->list->addView(this->dump_decrypted_cardinfo);
this->dump_initial_data = new brls::ListItem("gamecard_tab/list/dump_initial_data/label"_i18n, "gamecard_tab/list/dump_initial_data/description"_i18n);
this->AddListView(this->dump_initial_data);
this->list->addView(this->dump_initial_data);
this->dump_hfs_partitions = new brls::ListItem("gamecard_tab/list/dump_hfs_partitions/label"_i18n, "gamecard_tab/list/dump_hfs_partitions/description"_i18n);
this->AddListView(this->dump_hfs_partitions);
this->list->addView(this->dump_hfs_partitions);
/* Subscribe to gamecard status event. */
this->gc_status_task_sub = this->gc_status_task->RegisterListener([this](GameCardStatus gc_status) {
@ -87,19 +88,19 @@ namespace nxdt::views
switch(gc_status)
{
case GameCardStatus_NotInserted:
this->SetErrorFrameMessage("gamecard_tab/error_frame/not_inserted"_i18n);
this->error_frame->SetMessage("gamecard_tab/error_frame/not_inserted"_i18n);
break;
case GameCardStatus_Processing:
this->SetErrorFrameMessage("gamecard_tab/error_frame/processing"_i18n);
this->error_frame->SetMessage("gamecard_tab/error_frame/processing"_i18n);
break;
case GameCardStatus_NoGameCardPatchEnabled:
this->SetErrorFrameMessage("gamecard_tab/error_frame/nogc_enabled"_i18n);
this->error_frame->SetMessage("gamecard_tab/error_frame/nogc_enabled"_i18n);
break;
case GameCardStatus_LotusAsicFirmwareUpdateRequired:
this->SetErrorFrameMessage("gamecard_tab/error_frame/lafw_update_required"_i18n);
this->error_frame->SetMessage("gamecard_tab/error_frame/lafw_update_required"_i18n);
break;
case GameCardStatus_InsertedAndInfoNotLoaded:
this->SetErrorFrameMessage(i18n::getStr("gamecard_tab/error_frame/info_not_loaded"_i18n, GITHUB_NEW_ISSUE_URL));
this->error_frame->SetMessage(i18n::getStr("gamecard_tab/error_frame/info_not_loaded"_i18n, GITHUB_NEW_ISSUE_URL));
break;
case GameCardStatus_InsertedAndInfoLoaded:
{

View file

@ -23,56 +23,35 @@
namespace nxdt::views
{
LayeredErrorFrame::LayeredErrorFrame(void) : brls::LayerView()
LayeredErrorFrame::LayeredErrorFrame(std::string msg) : brls::LayerView()
{
/* Error frame. */
this->error_frame = new ErrorFrame();
this->error_frame = new ErrorFrame(msg);
this->addLayer(this->error_frame);
/* List. */
this->list = new brls::List();
this->list->setSpacing(this->list->getSpacing() / 2);
this->list->setMarginBottom(20);
this->addLayer(this->list);
}
LayeredErrorFrame::~LayeredErrorFrame(void)
{
/* Clear list views vector. */
if (this->list_views.size()) this->list_views.clear();
}
void LayeredErrorFrame::SwitchLayerView(bool use_error_frame)
{
if ((use_error_frame && this->layer_view_index == 0) || (!use_error_frame && this->layer_view_index == 1)) return;
int index = this->getLayerIndex();
int new_index = (index ^ 1);
brls::View *cur_focus = brls::Application::getCurrentFocus();
int index = (this->layer_view_index ^ 1);
brls::View *current_focus = brls::Application::getCurrentFocus();
/* Don't proceed if we're already at the desired view layer. */
if (index < 0 || index > 1 || (use_error_frame && index == 0) || (!use_error_frame && index == 1)) return;
/* Focus the sidebar if we're currently focusing an element from our List. */
for(brls::View* list_view : this->list_views)
/* Focus the sidebar if we're currently focusing an element from our List and we're about to switch to the error frame. */
if (use_error_frame && cur_focus && cur_focus->hasParent())
{
if (current_focus == list_view)
{
brls::Application::onGamepadButtonPressed(GLFW_GAMEPAD_BUTTON_DPAD_LEFT, false);
break;
}
brls::View *cur_focus_parent = cur_focus->getParent();
if (cur_focus_parent && cur_focus_parent->hasParent() && cur_focus_parent->getParent() == this->list) brls::Application::onGamepadButtonPressed(GLFW_GAMEPAD_BUTTON_DPAD_LEFT, false);
}
/* Change layer view. */
this->changeLayer(index);
this->changeLayer(new_index);
this->invalidate(true);
this->layer_view_index = index;
}
void LayeredErrorFrame::SetErrorFrameMessage(std::string msg)
{
this->error_frame->SetMessage(msg);
}
void LayeredErrorFrame::AddListView(brls::View* view)
{
this->list->addView(view);
this->list_views.push_back(view);
}
}

View file

@ -22,7 +22,7 @@
#include <nxdt_utils.h>
#include <root_view.hpp>
#include <gamecard_tab.hpp>
//#include <user_titles_tab.hpp>
#include <user_titles_tab.hpp>
//#include <system_titles_tab.hpp>
//#include <options_tab.hpp>
#include <about_tab.hpp>
@ -73,7 +73,7 @@ namespace nxdt::views
/* Add tabs. */
this->addTab("root_view/tabs/gamecard"_i18n, new GameCardTab(this->gc_status_task));
this->addSeparator();
this->addTab("root_view/tabs/user_titles"_i18n, new brls::Rectangle(nvgRGB(0, 255, 0)));
this->addTab("root_view/tabs/user_titles"_i18n, new UserTitlesTab(this->title_task));
this->addTab("root_view/tabs/system_titles"_i18n, new brls::Rectangle(nvgRGB(0, 0, 255)));
this->addSeparator();
this->addTab("root_view/tabs/options"_i18n, new brls::Rectangle(nvgRGB(255, 255, 0)));

100
source/user_titles_tab.cpp Normal file
View file

@ -0,0 +1,100 @@
/*
* user_titles_tab.cpp
*
* Copyright (c) 2020-2021, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
*
* nxdumptool is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* nxdumptool is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <nxdt_utils.h>
#include <user_titles_tab.hpp>
namespace i18n = brls::i18n; /* For getStr(). */
using namespace i18n::literals; /* For _i18n. */
namespace nxdt::views
{
UserTitlesTab::UserTitlesTab(nxdt::tasks::TitleTask *title_task) : LayeredErrorFrame("user_titles_tab/error_frame/no_titles_available"_i18n), title_task(title_task)
{
/* Populate list. */
this->PopulateList();
/* Subscribe to title event. */
this->title_task_sub = this->title_task->RegisterListener([this](void) {
/* Update list. */
this->PopulateList();
});
}
UserTitlesTab::~UserTitlesTab(void)
{
/* Unregister task listener. */
this->title_task->UnregisterListener(this->title_task_sub);
}
void UserTitlesTab::PopulateList(void)
{
bool refocus = false;
this->user_app_metadata = this->title_task->GetApplicationMetadata(false);
size_t user_app_metadata_count = this->user_app_metadata->size();
if (user_app_metadata_count)
{
/* Determine if we need to refocus after updating the list. */
brls::View *cur_view = brls::Application::getCurrentFocus();
while(cur_view)
{
if (cur_view == this->list)
{
refocus = true;
break;
}
cur_view = cur_view->getParent();
}
} else {
/* If we need to, switch to the error frame *before* cleaning up our list. */
this->SwitchLayerView(true);
}
/* Clear list. */
this->list->clear();
this->list->invalidate(true);
/* Immediately return if we have no user application metadata. */
if (!user_app_metadata_count) return;
/* Populate list. */
for(TitleApplicationMetadata *cur_app_metadata : *(this->user_app_metadata))
{
brls::ListItem *list_item = new brls::ListItem(std::string(cur_app_metadata->lang_entry.name), "", std::string(cur_app_metadata->lang_entry.author));
list_item->setThumbnail(cur_app_metadata->icon, cur_app_metadata->icon_size);
this->list->addView(list_item);
}
/* Switch to the list. */
this->list->invalidate(true);
this->SwitchLayerView(false);
/* Refocus, if needed. */
if (refocus)
{
brls::Application::giveFocus(this->list->getChild(0));
this->list->willAppear(true);
}
}
}