diff --git a/include/error_frame.hpp b/include/error_frame.hpp index 5802542..6313866 100644 --- a/include/error_frame.hpp +++ b/include/error_frame.hpp @@ -40,7 +40,7 @@ namespace nxdt::views void layout(NVGcontext* vg, brls::Style* style, brls::FontStash* stash) override; public: - ErrorFrame(std::string msg); + ErrorFrame(std::string msg = ""); ~ErrorFrame(void); void SetMessage(std::string msg); diff --git a/include/error_layer_view.hpp b/include/error_layer_view.hpp new file mode 100644 index 0000000..0803d49 --- /dev/null +++ b/include/error_layer_view.hpp @@ -0,0 +1,129 @@ +/* + * error_layer_view.hpp + * + * Copyright (c) 2020-2021, DarkMatterCore . + * + * 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 . + */ + +#pragma once + +#ifndef __ERROR_LAYER_VIEW_HPP__ +#define __ERROR_LAYER_VIEW_HPP__ + +#include "error_frame.hpp" + +namespace nxdt::views +{ + /* Extended class to switch between ErrorFrame and List views whenever an event is triggered. */ + template + class ErrorLayerView: public brls::LayerView + { + private: + TaskType *task = nullptr; + std::vector task_subs; + + ErrorFrame *error_frame = nullptr; + + brls::List *list = nullptr; + std::vector list_views; + + int layer_view_index = 0; + + protected: + void SwitchLayerView(bool use_error_frame); + void SetErrorFrameMessage(std::string msg = ""); + void AddListView(brls::View* view); + void RegisterListener(typename EventType::Callback cb); + + public: + ErrorLayerView(TaskType *task); + ~ErrorLayerView(void); + }; + + template + ErrorLayerView::ErrorLayerView(TaskType *task) : brls::LayerView(), task(task) + { + /* Error frame. */ + this->error_frame = new ErrorFrame(); + 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); + } + + template + ErrorLayerView::~ErrorLayerView(void) + { + /* Unregister task listeners. */ + for(typename EventType::Subscription task_sub : this->task_subs) this->task->UnregisterListener(task_sub); + + /* Clear task subscriptions vector. */ + if (this->task_subs.size()) this->task_subs.clear(); + + /* Clear list views vector. */ + if (this->list_views.size()) this->list_views.clear(); + } + + template + void ErrorLayerView::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->layer_view_index ^ 1); + brls::View *current_focus = brls::Application::getCurrentFocus(); + + /* Focus the sidebar if we're currently focusing an element from our List. */ + for(brls::View* list_view : this->list_views) + { + if (current_focus == list_view) + { + brls::Application::onGamepadButtonPressed(GLFW_GAMEPAD_BUTTON_DPAD_LEFT, false); + break; + } + } + + /* Change layer view. */ + this->changeLayer(index); + this->invalidate(true); + this->layer_view_index = index; + } + + template + void ErrorLayerView::SetErrorFrameMessage(std::string msg) + { + this->error_frame->SetMessage(msg); + } + + template + void ErrorLayerView::AddListView(brls::View* view) + { + this->list->addView(view); + this->list_views.push_back(view); + } + + template + void ErrorLayerView::RegisterListener(typename EventType::Callback cb) + { + typename EventType::Subscription task_sub = this->task->RegisterListener(cb); + this->task_subs.push_back(task_sub); + } +} + +#endif /* __ERROR_LAYER_VIEW_HPP__ */ diff --git a/include/gamecard_tab.hpp b/include/gamecard_tab.hpp index a07b024..ba6f859 100644 --- a/include/gamecard_tab.hpp +++ b/include/gamecard_tab.hpp @@ -25,7 +25,7 @@ #define __GAMECARD_TAB_HPP__ #include "tasks.hpp" -#include "error_frame.hpp" +#include "error_layer_view.hpp" namespace nxdt::views { @@ -40,20 +40,16 @@ namespace nxdt::views GameCardTable(void); }; - /* Extended class to switch between ErrorFrame and List views whenever the gamecard status event is triggered. */ - class GameCardTab: public brls::LayerView + /* Instantiate the template for our class. */ + typedef ErrorLayerView GameCardErrorLayerView; + + class GameCardTab: public GameCardErrorLayerView { typedef bool (*GameCardSizeFunc)(u64 *size); private: - nxdt::tasks::GameCardTask *gc_status_task = nullptr; - nxdt::tasks::GameCardStatusEvent::Subscription gc_status_task_sub; GameCardStatus gc_status = GameCardStatus_NotInserted; - ErrorFrame *error_frame = nullptr; - - brls::List *list = nullptr; - GameCardTable *properties_table = nullptr; brls::TableRow *capacity = nullptr; brls::TableRow *total_size = nullptr; @@ -70,17 +66,10 @@ namespace nxdt::views brls::ListItem *dump_initial_data = nullptr; brls::ListItem *dump_hfs_partitions = nullptr; - std::vector views; - int view_index = -1; - - void addLayerWrapper(brls::View* view); - void changeLayerWrapper(brls::View* view); - std::string GetFormattedSizeString(GameCardSizeFunc func); public: GameCardTab(nxdt::tasks::GameCardTask *gc_status_task); - ~GameCardTab(void); }; } diff --git a/include/root_view.hpp b/include/root_view.hpp index e5b8d5d..edd965a 100644 --- a/include/root_view.hpp +++ b/include/root_view.hpp @@ -39,7 +39,7 @@ namespace nxdt::views nxdt::tasks::UmsTask *ums_task = nullptr; nxdt::tasks::UsbHostTask *usb_host_task = nullptr; - brls::VoidEvent::Subscription status_info_task_sub; + nxdt::tasks::VoidEvent::Subscription status_info_task_sub; brls::Label *applet_mode_lbl = nullptr; brls::Label *time_lbl = nullptr; diff --git a/source/gamecard_tab.cpp b/source/gamecard_tab.cpp index 6351009..6d6e52a 100644 --- a/source/gamecard_tab.cpp +++ b/source/gamecard_tab.cpp @@ -55,19 +55,13 @@ namespace nxdt::views if (this->hasParent()) this->getParent()->onChildFocusGained(this); } - GameCardTab::GameCardTab(nxdt::tasks::GameCardTask *gc_status_task) : brls::LayerView(), gc_status_task(gc_status_task) + GameCardTab::GameCardTab(nxdt::tasks::GameCardTask *gc_status_task) : GameCardErrorLayerView(gc_status_task) { /* Error frame. */ - this->error_frame = new ErrorFrame("gamecard_tab/error_frame/not_inserted"_i18n); - this->addLayerWrapper(this->error_frame); - - /* List. */ - this->list = new brls::List(); - this->list->setSpacing(this->list->getSpacing() / 2); - this->list->setMarginBottom(20); + this->SetErrorFrameMessage("gamecard_tab/error_frame/not_inserted"_i18n); /* Gamecard properties table. */ - this->list->addView(new brls::Header("gamecard_tab/list/properties_table/header"_i18n)); + this->AddListView(new brls::Header("gamecard_tab/list/properties_table/header"_i18n)); this->properties_table = new GameCardTable(); this->capacity = this->properties_table->addRow(brls::TableRowType::BODY, "gamecard_tab/list/properties_table/capacity"_i18n); @@ -77,51 +71,49 @@ 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->list->addView(this->properties_table); + this->AddListView(this->properties_table); /* ListItem elements. */ - this->list->addView(new brls::Header("gamecard_tab/list/dump_options"_i18n)); + this->AddListView(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->list->addView(this->dump_card_image); + this->AddListView(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->list->addView(this->dump_certificate); + this->AddListView(this->dump_certificate); this->dump_header = new brls::ListItem("gamecard_tab/list/dump_header/label"_i18n, "gamecard_tab/list/dump_header/description"_i18n); - this->list->addView(this->dump_header); + this->AddListView(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->list->addView(this->dump_decrypted_cardinfo); + this->AddListView(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->list->addView(this->dump_initial_data); + this->AddListView(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->list->addView(this->dump_hfs_partitions); - - this->addLayerWrapper(this->list); + this->AddListView(this->dump_hfs_partitions); /* Subscribe to gamecard status event. */ - this->gc_status_task_sub = this->gc_status_task->RegisterListener([this](GameCardStatus gc_status) { - if (gc_status < GameCardStatus_InsertedAndInfoLoaded) this->changeLayerWrapper(this->error_frame); + this->RegisterListener([this](GameCardStatus gc_status) { + if (gc_status < GameCardStatus_InsertedAndInfoLoaded) this->SwitchLayerView(true); switch(gc_status) { case GameCardStatus_NotInserted: - this->error_frame->SetMessage("gamecard_tab/error_frame/not_inserted"_i18n); + this->SetErrorFrameMessage("gamecard_tab/error_frame/not_inserted"_i18n); break; case GameCardStatus_Processing: - this->error_frame->SetMessage("gamecard_tab/error_frame/processing"_i18n); + this->SetErrorFrameMessage("gamecard_tab/error_frame/processing"_i18n); break; case GameCardStatus_NoGameCardPatchEnabled: - this->error_frame->SetMessage("gamecard_tab/error_frame/nogc_enabled"_i18n); + this->SetErrorFrameMessage("gamecard_tab/error_frame/nogc_enabled"_i18n); break; case GameCardStatus_LotusAsicFirmwareUpdateRequired: - this->error_frame->SetMessage("gamecard_tab/error_frame/lafw_update_required"_i18n); + this->SetErrorFrameMessage("gamecard_tab/error_frame/lafw_update_required"_i18n); break; case GameCardStatus_InsertedAndInfoNotLoaded: - this->error_frame->SetMessage(i18n::getStr("gamecard_tab/error_frame/info_not_loaded"_i18n, GITHUB_NEW_ISSUE_URL)); + this->SetErrorFrameMessage(i18n::getStr("gamecard_tab/error_frame/info_not_loaded"_i18n, GITHUB_NEW_ISSUE_URL)); break; case GameCardStatus_InsertedAndInfoLoaded: { @@ -147,7 +139,7 @@ namespace nxdt::views compatibility_type >= GameCardCompatibilityType_Count ? "generic/unknown"_i18n : GameCardCompatibilityTypeStrings[compatibility_type], \ compatibility_type)); - this->changeLayerWrapper(this->list); + this->SwitchLayerView(false); break; } @@ -159,50 +151,6 @@ namespace nxdt::views }); } - GameCardTab::~GameCardTab(void) - { - /* Unregister gamecard task listener. */ - this->gc_status_task->UnregisterListener(this->gc_status_task_sub); - - /* Clear views vector. */ - if (this->views.size()) this->views.clear(); - } - - void GameCardTab::addLayerWrapper(brls::View* view) - { - this->views.push_back(view); - this->addLayer(view); - if (this->view_index == -1) this->view_index = 0; - } - - void GameCardTab::changeLayerWrapper(brls::View* view) - { - int index = -1; - brls::View *current_focus = brls::Application::getCurrentFocus(); - - for(size_t i = 0; i < this->views.size(); i++) - { - if (this->views[i] == view) - { - index = (int)i; - break; - } - } - - if (index == -1) return; - - /* Focus the sidebar if we're currently focusing an element from our List. */ - if (current_focus && (current_focus == this->properties_table || current_focus == this->dump_card_image || current_focus == this->dump_certificate || current_focus == this->dump_header || \ - current_focus == this->dump_decrypted_cardinfo || current_focus == this->dump_initial_data || current_focus == this->dump_hfs_partitions)) - { - brls::Application::onGamepadButtonPressed(GLFW_GAMEPAD_BUTTON_DPAD_LEFT, false); - } - - this->changeLayer(index); - this->invalidate(true); - this->view_index = index; - } - std::string GameCardTab::GetFormattedSizeString(GameCardSizeFunc func) { u64 size = 0;