Extract the class TabbedUIDialogScreen from GameSettingsScreen.

This commit is contained in:
Henrik Rydgård 2023-06-16 13:44:35 +02:00
parent 6d4e5a0f3e
commit fffaa41091
10 changed files with 237 additions and 177 deletions

View file

@ -1368,6 +1368,8 @@ list(APPEND NativeAppSource
UI/MiscScreens.cpp UI/MiscScreens.cpp
UI/PauseScreen.h UI/PauseScreen.h
UI/PauseScreen.cpp UI/PauseScreen.cpp
UI/TabbedDialogScreen.h
UI/TabbedDialogScreen.cpp
UI/GameScreen.h UI/GameScreen.h
UI/GameScreen.cpp UI/GameScreen.cpp
UI/GameSettingsScreen.h UI/GameSettingsScreen.h

View file

@ -95,7 +95,7 @@ extern AndroidAudioState *g_audioState;
#endif #endif
GameSettingsScreen::GameSettingsScreen(const Path &gamePath, std::string gameID, bool editThenRestore) GameSettingsScreen::GameSettingsScreen(const Path &gamePath, std::string gameID, bool editThenRestore)
: UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), editThenRestore_(editThenRestore) { : TabbedUIDialogScreenWithGameBackground(gamePath), gameID_(gameID), editThenRestore_(editThenRestore) {
prevInflightFrames_ = g_Config.iInflightFrames; prevInflightFrames_ = g_Config.iInflightFrames;
analogSpeedMapped_ = KeyMap::InputMappingsFromPspButton(VIRTKEY_SPEED_ANALOG, nullptr, true); analogSpeedMapped_ = KeyMap::InputMappingsFromPspButton(VIRTKEY_SPEED_ANALOG, nullptr, true);
} }
@ -191,7 +191,7 @@ static std::string PostShaderTranslateName(const char *value) {
} }
} }
void GameSettingsScreen::CreateViews() { void GameSettingsScreen::PreCreateViews() {
ReloadAllPostShaderInfo(screenManager()->getDrawContext()); ReloadAllPostShaderInfo(screenManager()->getDrawContext());
ReloadAllThemeInfo(); ReloadAllThemeInfo();
@ -203,49 +203,11 @@ void GameSettingsScreen::CreateViews() {
iAlternateSpeedPercent1_ = g_Config.iFpsLimit1 < 0 ? -1 : (g_Config.iFpsLimit1 * 100) / 60; iAlternateSpeedPercent1_ = g_Config.iFpsLimit1 < 0 ? -1 : (g_Config.iFpsLimit1 * 100) / 60;
iAlternateSpeedPercent2_ = g_Config.iFpsLimit2 < 0 ? -1 : (g_Config.iFpsLimit2 * 100) / 60; iAlternateSpeedPercent2_ = g_Config.iFpsLimit2 < 0 ? -1 : (g_Config.iFpsLimit2 * 100) / 60;
iAlternateSpeedPercentAnalog_ = (g_Config.iAnalogFpsLimit * 100) / 60; iAlternateSpeedPercentAnalog_ = (g_Config.iAnalogFpsLimit * 100) / 60;
}
bool vertical = UseVerticalLayout(); void GameSettingsScreen::CreateTabs() {
// Information in the top left.
// Back button to the bottom left.
// Scrolling action menu to the right.
using namespace UI; using namespace UI;
auto ms = GetI18NCategory(I18NCat::MAINSETTINGS); auto ms = GetI18NCategory(I18NCat::MAINSETTINGS);
auto di = GetI18NCategory(I18NCat::DIALOG);
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
if (vertical) {
LinearLayout *verticalLayout = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, new LinearLayoutParams(1.0f));
verticalLayout->Add(tabHolder_);
verticalLayout->Add(new Choice(di->T("Back"), "", false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f, Margins(0))))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
root_->Add(verticalLayout);
} else {
tabHolder_ = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false));
root_->Add(tabHolder_);
AddStandardBack(root_);
}
tabHolder_->SetTag("GameSettings");
root_->SetDefaultFocusView(tabHolder_);
settingTabContents_.clear();
settingTabFilterNotices_.clear();
float leftSide = 40.0f;
if (!vertical) {
leftSide += 200.0f;
}
settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams(
g_display.dp_xres - leftSide - 40.0f, WRAP_CONTENT,
leftSide, g_display.dp_yres - 80.0f - 40.0f, NONE, NONE));
settingInfo_->SetBottomCutoff(g_display.dp_yres - 200.0f);
root_->Add(settingInfo_);
// Show it again if we recreated the view
if (!oldSettingInfo_.empty()) {
settingInfo_->Show(oldSettingInfo_, nullptr);
}
LinearLayout *graphicsSettings = AddTab("GameSettingsGraphics", ms->T("Graphics")); LinearLayout *graphicsSettings = AddTab("GameSettingsGraphics", ms->T("Graphics"));
CreateGraphicsSettings(graphicsSettings); CreateGraphicsSettings(graphicsSettings);
@ -271,27 +233,6 @@ void GameSettingsScreen::CreateViews() {
LinearLayout *vrSettings = AddTab("GameSettingsVR", ms->T("VR")); LinearLayout *vrSettings = AddTab("GameSettingsVR", ms->T("VR"));
CreateVRSettings(vrSettings); CreateVRSettings(vrSettings);
} }
#if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID)
// Hide search if screen is too small.
if ((g_display.dp_xres < g_display.dp_yres || g_display.dp_yres >= 500) && (deviceType != DEVICE_TYPE_VR)) {
auto se = GetI18NCategory(I18NCat::SEARCH);
// Search
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);
searchSettings->Add(new ItemHeader(se->T("Find settings")));
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), I18NCat::NONE))->OnClick.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
} else {
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
}
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
clearSearchChoice_->OnClick.Handle(this, &GameSettingsScreen::OnClearSearchFilter);
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
ApplySearchFilter();
}
#endif
} }
// Graphics // Graphics
@ -1174,29 +1115,6 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) {
vrSettings->Add(new PopupMultiChoice(&g_Config.iCameraPitch, vr->T("Camera type"), cameraPitchModes, 0, 3, I18NCat::NONE, screenManager())); vrSettings->Add(new PopupMultiChoice(&g_Config.iCameraPitch, vr->T("Camera type"), cameraPitchModes, 0, 3, I18NCat::NONE, screenManager()));
} }
UI::LinearLayout *GameSettingsScreen::AddTab(const char *tag, const std::string &title, bool isSearch) {
auto se = GetI18NCategory(I18NCat::SEARCH);
using namespace UI;
ViewGroup *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
scroll->SetTag(tag);
LinearLayout *contents = new LinearLayoutList(ORIENT_VERTICAL);
contents->SetSpacing(0);
scroll->Add(contents);
tabHolder_->AddTab(title, scroll);
if (!isSearch) {
settingTabContents_.push_back(contents);
auto notice = contents->Add(new TextView(se->T("Filtering settings by '%1'"), new LinearLayoutParams(Margins(20, 5))));
notice->SetVisibility(V_GONE);
settingTabFilterNotices_.push_back(notice);
}
return contents;
}
UI::EventReturn GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) {
g_Config.UpdateAfterSettingAutoFrameSkip(); g_Config.UpdateAfterSettingAutoFrameSkip();
return UI::EVENT_DONE; return UI::EVENT_DONE;
@ -1378,54 +1296,6 @@ void GameSettingsScreen::onFinish(DialogResult result) {
NativeMessageReceived("gpu_configChanged", ""); NativeMessageReceived("gpu_configChanged", "");
} }
void GameSettingsScreen::sendMessage(const char *message, const char *value) {
UIDialogScreenWithGameBackground::sendMessage(message, value);
if (!strcmp(message, "gameSettings_search")) {
std::string filter = value ? value : "";
searchFilter_.resize(filter.size());
std::transform(filter.begin(), filter.end(), searchFilter_.begin(), tolower);
ApplySearchFilter();
}
}
void GameSettingsScreen::ApplySearchFilter() {
auto se = GetI18NCategory(I18NCat::SEARCH);
bool matches = searchFilter_.empty();
for (int t = 0; t < (int)settingTabContents_.size(); ++t) {
auto tabContents = settingTabContents_[t];
bool tabMatches = searchFilter_.empty();
// Show an indicator that a filter is applied.
settingTabFilterNotices_[t]->SetVisibility(tabMatches ? UI::V_GONE : UI::V_VISIBLE);
settingTabFilterNotices_[t]->SetText(ReplaceAll(se->T("Filtering settings by '%1'"), "%1", searchFilter_));
UI::View *lastHeading = nullptr;
for (int i = 1; i < tabContents->GetNumSubviews(); ++i) {
UI::View *v = tabContents->GetViewByIndex(i);
if (!v->CanBeFocused()) {
lastHeading = v;
}
std::string label = v->DescribeText();
std::transform(label.begin(), label.end(), label.begin(), tolower);
bool match = v->CanBeFocused() && label.find(searchFilter_) != label.npos;
tabMatches = tabMatches || match;
if (match && lastHeading)
lastHeading->SetVisibility(UI::V_VISIBLE);
v->SetVisibility(searchFilter_.empty() || match ? UI::V_VISIBLE : UI::V_GONE);
}
tabHolder_->EnableTab(t, tabMatches);
matches = matches || tabMatches;
}
noSearchResults_->SetText(ReplaceAll(se->T("No settings matched '%1'"), "%1", searchFilter_));
noSearchResults_->SetVisibility(matches ? UI::V_GONE : UI::V_VISIBLE);
clearSearchChoice_->SetVisibility(searchFilter_.empty() ? UI::V_GONE : UI::V_VISIBLE);
}
void GameSettingsScreen::dialogFinished(const Screen *dialog, DialogResult result) { void GameSettingsScreen::dialogFinished(const Screen *dialog, DialogResult result) {
if (result == DialogResult::DR_OK) { if (result == DialogResult::DR_OK) {
g_Config.iFpsLimit1 = iAlternateSpeedPercent1_ < 0 ? -1 : (iAlternateSpeedPercent1_ * 60) / 100; g_Config.iFpsLimit1 = iAlternateSpeedPercent1_ < 0 ? -1 : (iAlternateSpeedPercent1_ * 60) / 100;
@ -1442,11 +1312,6 @@ void GameSettingsScreen::dialogFinished(const Screen *dialog, DialogResult resul
} }
} }
void GameSettingsScreen::RecreateViews() {
oldSettingInfo_ = settingInfo_ ? settingInfo_->GetText() : "N/A";
UIScreen::RecreateViews();
}
void GameSettingsScreen::CallbackMemstickFolder(bool yes) { void GameSettingsScreen::CallbackMemstickFolder(bool yes) {
auto sy = GetI18NCategory(I18NCat::SYSTEM); auto sy = GetI18NCategory(I18NCat::SYSTEM);
@ -1721,24 +1586,6 @@ UI::EventReturn GameSettingsScreen::OnSysInfo(UI::EventParams &e) {
return UI::EVENT_DONE; return UI::EVENT_DONE;
} }
UI::EventReturn GameSettingsScreen::OnChangeSearchFilter(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__)
auto se = GetI18NCategory(I18NCat::SEARCH);
System_InputBoxGetString(se->T("Search term"), searchFilter_, [](const std::string &value, int) {
NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str());
});
#else
if (!System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
NativeMessageReceived("gameSettings_search", StripSpaces(searchFilter_).c_str());
#endif
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnClearSearchFilter(UI::EventParams &e) {
NativeMessageReceived("gameSettings_search", "");
return UI::EVENT_DONE;
}
void DeveloperToolsScreen::CreateViews() { void DeveloperToolsScreen::CreateViews() {
using namespace UI; using namespace UI;
root_ = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)); root_ = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));

View file

@ -25,10 +25,11 @@
#include "Common/UI/UIScreen.h" #include "Common/UI/UIScreen.h"
#include "Core/ConfigValues.h" #include "Core/ConfigValues.h"
#include "UI/MiscScreens.h" #include "UI/MiscScreens.h"
#include "UI/TabbedDialogScreen.h"
// Per-game settings screen - enables you to configure graphic options, control options, etc // Per-game settings screen - enables you to configure graphic options, control options, etc
// per game. // per game.
class GameSettingsScreen : public UIDialogScreenWithGameBackground { class GameSettingsScreen : public TabbedUIDialogScreenWithGameBackground {
public: public:
GameSettingsScreen(const Path &gamePath, std::string gameID = "", bool editThenRestore = false); GameSettingsScreen(const Path &gamePath, std::string gameID = "", bool editThenRestore = false);
@ -36,17 +37,18 @@ public:
const char *tag() const override { return "GameSettings"; } const char *tag() const override { return "GameSettings"; }
protected: protected:
void sendMessage(const char *message, const char *value) override;
void CreateViews() override;
void CallbackRestoreDefaults(bool yes); void CallbackRestoreDefaults(bool yes);
void CallbackRenderingBackend(bool yes); void CallbackRenderingBackend(bool yes);
void CallbackRenderingDevice(bool yes); void CallbackRenderingDevice(bool yes);
void CallbackInflightFrames(bool yes); void CallbackInflightFrames(bool yes);
void CallbackMemstickFolder(bool yes); void CallbackMemstickFolder(bool yes);
void dialogFinished(const Screen *dialog, DialogResult result) override; void dialogFinished(const Screen *dialog, DialogResult result) override;
void RecreateViews() override;
void CreateTabs() override;
private: private:
void PreCreateViews() override;
void CreateGraphicsSettings(UI::ViewGroup *graphicsSettings); void CreateGraphicsSettings(UI::ViewGroup *graphicsSettings);
void CreateControlsSettings(UI::ViewGroup *tools); void CreateControlsSettings(UI::ViewGroup *tools);
void CreateAudioSettings(UI::ViewGroup *audioSettings); void CreateAudioSettings(UI::ViewGroup *audioSettings);
@ -55,8 +57,6 @@ private:
void CreateSystemSettings(UI::ViewGroup *systemSettings); void CreateSystemSettings(UI::ViewGroup *systemSettings);
void CreateVRSettings(UI::ViewGroup *vrSettings); void CreateVRSettings(UI::ViewGroup *vrSettings);
UI::LinearLayout *AddTab(const char *tag, const std::string &title, bool isSearch = false);
void ApplySearchFilter();
void TriggerRestart(const char *why); void TriggerRestart(const char *why);
std::string gameID_; std::string gameID_;
@ -66,9 +66,6 @@ private:
UI::Choice *backgroundChoice_ = nullptr; UI::Choice *backgroundChoice_ = nullptr;
UI::PopupMultiChoice *resolutionChoice_ = nullptr; UI::PopupMultiChoice *resolutionChoice_ = nullptr;
UI::CheckBox *frameSkipAuto_ = nullptr; UI::CheckBox *frameSkipAuto_ = nullptr;
SettingInfoMessage *settingInfo_ = nullptr;
UI::Choice *clearSearchChoice_ = nullptr;
UI::TextView *noSearchResults_ = nullptr;
#ifdef _WIN32 #ifdef _WIN32
UI::CheckBox *SavePathInMyDocumentChoice = nullptr; UI::CheckBox *SavePathInMyDocumentChoice = nullptr;
UI::CheckBox *SavePathInOtherChoice = nullptr; UI::CheckBox *SavePathInOtherChoice = nullptr;
@ -79,10 +76,6 @@ private:
std::string memstickDisplay_; std::string memstickDisplay_;
UI::TabHolder *tabHolder_ = nullptr;
std::vector<UI::LinearLayout *> settingTabContents_;
std::vector<UI::TextView *> settingTabFilterNotices_;
// Event handlers // Event handlers
UI::EventReturn OnControlMapping(UI::EventParams &e); UI::EventReturn OnControlMapping(UI::EventParams &e);
UI::EventReturn OnCalibrateAnalogs(UI::EventParams &e); UI::EventReturn OnCalibrateAnalogs(UI::EventParams &e);
@ -131,8 +124,6 @@ private:
UI::EventReturn OnSavedataManager(UI::EventParams &e); UI::EventReturn OnSavedataManager(UI::EventParams &e);
UI::EventReturn OnSysInfo(UI::EventParams &e); UI::EventReturn OnSysInfo(UI::EventParams &e);
UI::EventReturn OnChangeSearchFilter(UI::EventParams &e);
UI::EventReturn OnClearSearchFilter(UI::EventParams &e);
// Temporaries to convert setting types, cache enabled, etc. // Temporaries to convert setting types, cache enabled, etc.
int iAlternateSpeedPercent1_ = 0; int iAlternateSpeedPercent1_ = 0;
@ -143,16 +134,11 @@ private:
bool enableReportsSet_ = false; bool enableReportsSet_ = false;
bool analogSpeedMapped_ = false; bool analogSpeedMapped_ = false;
std::string searchFilter_;
// edit the game-specific settings and restore the global settings after exiting // edit the game-specific settings and restore the global settings after exiting
bool editThenRestore_ = false; bool editThenRestore_ = false;
// Android-only // Android-only
std::string pendingMemstickFolder_; std::string pendingMemstickFolder_;
// If we recreate the views while this is active we show it again
std::string oldSettingInfo_;
}; };
class DeveloperToolsScreen : public UIDialogScreenWithGameBackground { class DeveloperToolsScreen : public UIDialogScreenWithGameBackground {

173
UI/TabbedDialogScreen.cpp Normal file
View file

@ -0,0 +1,173 @@
#include <algorithm>
#include "Common/StringUtils.h"
#include "Common/System/NativeApp.h"
#include "Common/System/Request.h"
#include "Common/System/Display.h"
#include "UI/TabbedDialogScreen.h"
UI::LinearLayout *TabbedUIDialogScreenWithGameBackground::AddTab(const char *tag, const std::string &title, bool isSearch) {
auto se = GetI18NCategory(I18NCat::SEARCH);
using namespace UI;
ViewGroup *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
scroll->SetTag(tag);
LinearLayout *contents = new LinearLayoutList(ORIENT_VERTICAL);
contents->SetSpacing(0);
scroll->Add(contents);
tabHolder_->AddTab(title, scroll);
if (!isSearch) {
settingTabContents_.push_back(contents);
auto notice = contents->Add(new TextView(se->T("Filtering settings by '%1'"), new LinearLayoutParams(Margins(20, 5))));
notice->SetVisibility(V_GONE);
settingTabFilterNotices_.push_back(notice);
}
return contents;
}
void TabbedUIDialogScreenWithGameBackground::CreateViews() {
PreCreateViews();
bool vertical = UseVerticalLayout();
// Information in the top left.
// Back button to the bottom left.
// Scrolling action menu to the right.
using namespace UI;
auto ms = GetI18NCategory(I18NCat::MAINSETTINGS);
auto di = GetI18NCategory(I18NCat::DIALOG);
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
if (vertical) {
LinearLayout *verticalLayout = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, new LinearLayoutParams(1.0f));
verticalLayout->Add(tabHolder_);
verticalLayout->Add(new Choice(di->T("Back"), "", false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f, Margins(0))))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
root_->Add(verticalLayout);
} else {
tabHolder_ = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false));
root_->Add(tabHolder_);
AddStandardBack(root_);
}
tabHolder_->SetTag("GameSettings");
root_->SetDefaultFocusView(tabHolder_);
settingTabContents_.clear();
settingTabFilterNotices_.clear();
float leftSide = 40.0f;
if (!vertical) {
leftSide += 200.0f;
}
settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams(
g_display.dp_xres - leftSide - 40.0f, WRAP_CONTENT,
leftSide, g_display.dp_yres - 80.0f - 40.0f, NONE, NONE));
settingInfo_->SetBottomCutoff(g_display.dp_yres - 200.0f);
root_->Add(settingInfo_);
// Show it again if we recreated the view
if (!oldSettingInfo_.empty()) {
settingInfo_->Show(oldSettingInfo_, nullptr);
}
// Let the subclass create its tabs.
CreateTabs();
#if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID)
// Hide search if screen is too small.
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
if ((g_display.dp_xres < g_display.dp_yres || g_display.dp_yres >= 500) && (deviceType != DEVICE_TYPE_VR)) {
auto se = GetI18NCategory(I18NCat::SEARCH);
// Search
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);
searchSettings->Add(new ItemHeader(se->T("Find settings")));
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), I18NCat::NONE))->OnClick.Handle(this, &TabbedUIDialogScreenWithGameBackground::OnChangeSearchFilter);
} else {
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &TabbedUIDialogScreenWithGameBackground::OnChangeSearchFilter);
}
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
clearSearchChoice_->OnClick.Handle(this, &TabbedUIDialogScreenWithGameBackground::OnClearSearchFilter);
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
ApplySearchFilter();
}
#endif
}
void TabbedUIDialogScreenWithGameBackground::sendMessage(const char *message, const char *value) {
UIDialogScreenWithGameBackground::sendMessage(message, value);
if (!strcmp(message, "gameSettings_search")) {
std::string filter = value ? value : "";
searchFilter_.resize(filter.size());
std::transform(filter.begin(), filter.end(), searchFilter_.begin(), tolower);
ApplySearchFilter();
}
}
void TabbedUIDialogScreenWithGameBackground::RecreateViews() {
oldSettingInfo_ = settingInfo_ ? settingInfo_->GetText() : "N/A";
UIScreen::RecreateViews();
}
void TabbedUIDialogScreenWithGameBackground::ApplySearchFilter() {
auto se = GetI18NCategory(I18NCat::SEARCH);
bool matches = searchFilter_.empty();
for (int t = 0; t < (int)settingTabContents_.size(); ++t) {
auto tabContents = settingTabContents_[t];
bool tabMatches = searchFilter_.empty();
// Show an indicator that a filter is applied.
settingTabFilterNotices_[t]->SetVisibility(tabMatches ? UI::V_GONE : UI::V_VISIBLE);
settingTabFilterNotices_[t]->SetText(ReplaceAll(se->T("Filtering settings by '%1'"), "%1", searchFilter_));
UI::View *lastHeading = nullptr;
for (int i = 1; i < tabContents->GetNumSubviews(); ++i) {
UI::View *v = tabContents->GetViewByIndex(i);
if (!v->CanBeFocused()) {
lastHeading = v;
}
std::string label = v->DescribeText();
std::transform(label.begin(), label.end(), label.begin(), tolower);
bool match = v->CanBeFocused() && label.find(searchFilter_) != label.npos;
tabMatches = tabMatches || match;
if (match && lastHeading)
lastHeading->SetVisibility(UI::V_VISIBLE);
v->SetVisibility(searchFilter_.empty() || match ? UI::V_VISIBLE : UI::V_GONE);
}
tabHolder_->EnableTab(t, tabMatches);
matches = matches || tabMatches;
}
noSearchResults_->SetText(ReplaceAll(se->T("No settings matched '%1'"), "%1", searchFilter_));
noSearchResults_->SetVisibility(matches ? UI::V_GONE : UI::V_VISIBLE);
clearSearchChoice_->SetVisibility(searchFilter_.empty() ? UI::V_GONE : UI::V_VISIBLE);
}
UI::EventReturn TabbedUIDialogScreenWithGameBackground::OnChangeSearchFilter(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__)
auto se = GetI18NCategory(I18NCat::SEARCH);
System_InputBoxGetString(se->T("Search term"), searchFilter_, [](const std::string &value, int) {
NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str());
});
#else
if (!System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
NativeMessageReceived("gameSettings_search", StripSpaces(searchFilter_).c_str());
#endif
return UI::EVENT_DONE;
}
UI::EventReturn TabbedUIDialogScreenWithGameBackground::OnClearSearchFilter(UI::EventParams &e) {
NativeMessageReceived("gameSettings_search", "");
return UI::EVENT_DONE;
}

39
UI/TabbedDialogScreen.h Normal file
View file

@ -0,0 +1,39 @@
#pragma once
#include "ppsspp_config.h"
#include "Common/UI/UIScreen.h"
#include "Core/ConfigValues.h"
#include "UI/MiscScreens.h"
class TabbedUIDialogScreenWithGameBackground : public UIDialogScreenWithGameBackground {
public:
TabbedUIDialogScreenWithGameBackground(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) {}
UI::LinearLayout *AddTab(const char *tag, const std::string &title, bool isSearch = false);
void CreateViews() override;
protected:
// Load data and define your tabs here.
virtual void PreCreateViews() {}
virtual void CreateTabs() {};
void RecreateViews() override;
UI::EventReturn OnChangeSearchFilter(UI::EventParams &e);
UI::EventReturn OnClearSearchFilter(UI::EventParams &e);
SettingInfoMessage *settingInfo_ = nullptr;
private:
void sendMessage(const char *message, const char *value) override;
void ApplySearchFilter();
UI::TabHolder *tabHolder_ = nullptr;
std::vector<UI::LinearLayout *> settingTabContents_;
std::vector<UI::TextView *> settingTabFilterNotices_;
UI::Choice *clearSearchChoice_ = nullptr;
UI::TextView *noSearchResults_ = nullptr;
// If we recreate the views while this is active we show it again
std::string oldSettingInfo_;
std::string searchFilter_;
};

View file

@ -62,6 +62,7 @@
<ClCompile Include="SavedataScreen.cpp" /> <ClCompile Include="SavedataScreen.cpp" />
<ClCompile Include="Store.cpp" /> <ClCompile Include="Store.cpp" />
<ClCompile Include="AudioCommon.cpp" /> <ClCompile Include="AudioCommon.cpp" />
<ClCompile Include="TabbedDialogScreen.cpp" />
<ClCompile Include="TiltAnalogSettingsScreen.cpp" /> <ClCompile Include="TiltAnalogSettingsScreen.cpp" />
<ClCompile Include="TouchControlLayoutScreen.cpp" /> <ClCompile Include="TouchControlLayoutScreen.cpp" />
<ClCompile Include="TouchControlVisibilityScreen.cpp" /> <ClCompile Include="TouchControlVisibilityScreen.cpp" />
@ -95,6 +96,7 @@
<ClInclude Include="ReportScreen.h" /> <ClInclude Include="ReportScreen.h" />
<ClInclude Include="SavedataScreen.h" /> <ClInclude Include="SavedataScreen.h" />
<ClInclude Include="Store.h" /> <ClInclude Include="Store.h" />
<ClInclude Include="TabbedDialogScreen.h" />
<ClInclude Include="TiltAnalogSettingsScreen.h" /> <ClInclude Include="TiltAnalogSettingsScreen.h" />
<ClInclude Include="TouchControlLayoutScreen.h" /> <ClInclude Include="TouchControlLayoutScreen.h" />
<ClInclude Include="TouchControlVisibilityScreen.h" /> <ClInclude Include="TouchControlVisibilityScreen.h" />

View file

@ -83,6 +83,9 @@
<ClCompile Include="CustomButtonMappingScreen.cpp"> <ClCompile Include="CustomButtonMappingScreen.cpp">
<Filter>Screens</Filter> <Filter>Screens</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="TabbedDialogScreen.cpp">
<Filter>Screens</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="GameInfoCache.h" /> <ClInclude Include="GameInfoCache.h" />
@ -166,6 +169,9 @@
<ClInclude Include="CustomButtonMappingScreen.h"> <ClInclude Include="CustomButtonMappingScreen.h">
<Filter>Screens</Filter> <Filter>Screens</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="TabbedDialogScreen.h">
<Filter>Screens</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="Screens"> <Filter Include="Screens">

View file

@ -294,6 +294,7 @@
<ClInclude Include="..\..\UI\GPUDriverTestScreen.h" /> <ClInclude Include="..\..\UI\GPUDriverTestScreen.h" />
<ClInclude Include="..\..\UI\InstallZipScreen.h" /> <ClInclude Include="..\..\UI\InstallZipScreen.h" />
<ClInclude Include="..\..\UI\JoystickHistoryView.h" /> <ClInclude Include="..\..\UI\JoystickHistoryView.h" />
<ClInclude Include="..\..\UI\TabbedDialogScreen.h" />
<ClInclude Include="..\..\UI\Theme.h" /> <ClInclude Include="..\..\UI\Theme.h" />
<ClInclude Include="..\..\UI\MainScreen.h" /> <ClInclude Include="..\..\UI\MainScreen.h" />
<ClInclude Include="..\..\UI\MemStickScreen.h" /> <ClInclude Include="..\..\UI\MemStickScreen.h" />
@ -329,6 +330,7 @@
<ClCompile Include="..\..\UI\GPUDriverTestScreen.cpp" /> <ClCompile Include="..\..\UI\GPUDriverTestScreen.cpp" />
<ClCompile Include="..\..\UI\InstallZipScreen.cpp" /> <ClCompile Include="..\..\UI\InstallZipScreen.cpp" />
<ClCompile Include="..\..\UI\JoystickHistoryView.cpp" /> <ClCompile Include="..\..\UI\JoystickHistoryView.cpp" />
<ClCompile Include="..\..\UI\TabbedDialogScreen.cpp" />
<ClCompile Include="..\..\UI\Theme.cpp" /> <ClCompile Include="..\..\UI\Theme.cpp" />
<ClCompile Include="..\..\UI\MainScreen.cpp" /> <ClCompile Include="..\..\UI\MainScreen.cpp" />
<ClCompile Include="..\..\UI\MemStickScreen.cpp" /> <ClCompile Include="..\..\UI\MemStickScreen.cpp" />

View file

@ -34,6 +34,7 @@
<ClCompile Include="..\..\UI\JoystickHistoryView.cpp" /> <ClCompile Include="..\..\UI\JoystickHistoryView.cpp" />
<ClCompile Include="..\..\UI\AudioCommon.cpp" /> <ClCompile Include="..\..\UI\AudioCommon.cpp" />
<ClCompile Include="..\..\UI\CustomButtonMappingScreen.cpp" /> <ClCompile Include="..\..\UI\CustomButtonMappingScreen.cpp" />
<ClCompile Include="..\..\UI\TabbedDialogScreen.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="pch.h" /> <ClInclude Include="pch.h" />
@ -69,5 +70,6 @@
<ClInclude Include="..\..\UI\JoystickHistoryView.h" /> <ClInclude Include="..\..\UI\JoystickHistoryView.h" />
<ClInclude Include="..\..\UI\AudioCommon.h" /> <ClInclude Include="..\..\UI\AudioCommon.h" />
<ClInclude Include="..\..\UI\CustomButtonMappingScreen.h" /> <ClInclude Include="..\..\UI\CustomButtonMappingScreen.h" />
<ClInclude Include="..\..\UI\TabbedDialogScreen.h" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -727,6 +727,7 @@ LOCAL_SRC_FILES := \
$(SRC)/UI/DisplayLayoutScreen.cpp \ $(SRC)/UI/DisplayLayoutScreen.cpp \
$(SRC)/UI/EmuScreen.cpp \ $(SRC)/UI/EmuScreen.cpp \
$(SRC)/UI/MainScreen.cpp \ $(SRC)/UI/MainScreen.cpp \
$(SRC)/UI/TabbedDialogScreen.cpp \
$(SRC)/UI/MemStickScreen.cpp \ $(SRC)/UI/MemStickScreen.cpp \
$(SRC)/UI/MiscScreens.cpp \ $(SRC)/UI/MiscScreens.cpp \
$(SRC)/UI/RemoteISOScreen.cpp \ $(SRC)/UI/RemoteISOScreen.cpp \