mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #20152 from hrydgard/lazy-tab-loading
Settings: Load tabs on demand, instead of all at once
This commit is contained in:
commit
0afacd3c03
18 changed files with 379 additions and 199 deletions
|
@ -957,7 +957,7 @@ std::string GridLayoutList::DescribeText() const {
|
|||
return DescribeListOrdered(u->T("List:"));
|
||||
}
|
||||
|
||||
TabHolder::TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams)
|
||||
TabHolder::TabHolder(Orientation orientation, float stripSize, View *bannerView, LayoutParams *layoutParams)
|
||||
: LinearLayout(Opposite(orientation), layoutParams) {
|
||||
SetSpacing(0.0f);
|
||||
if (orientation == ORIENT_HORIZONTAL) {
|
||||
|
@ -979,8 +979,14 @@ TabHolder::TabHolder(Orientation orientation, float stripSize, LayoutParams *lay
|
|||
|
||||
Add(new Spacer(4.0f))->SetSeparator();
|
||||
|
||||
contents_ = new AnchorLayout(new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
|
||||
Add(contents_)->SetClip(true);
|
||||
ViewGroup *contentHolder_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
|
||||
if (bannerView) {
|
||||
contentHolder_->Add(bannerView);
|
||||
bannerView_ = bannerView;
|
||||
}
|
||||
contents_ = contentHolder_->Add(new AnchorLayout(new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f)));
|
||||
contents_->SetClip(true);
|
||||
Add(contentHolder_);
|
||||
}
|
||||
|
||||
void TabHolder::AddBack(UIScreen *parent) {
|
||||
|
@ -990,16 +996,56 @@ void TabHolder::AddBack(UIScreen *parent) {
|
|||
}
|
||||
}
|
||||
|
||||
void TabHolder::AddTabContents(std::string_view title, View *tabContents) {
|
||||
tabContents->ReplaceLayoutParams(new AnchorLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
void TabHolder::AddTabContents(std::string_view title, ViewGroup *tabContents) {
|
||||
tabs_.push_back(tabContents);
|
||||
tabStrip_->AddChoice(title);
|
||||
contents_->Add(tabContents);
|
||||
if (tabs_.size() > 1)
|
||||
tabContents->SetVisibility(V_GONE);
|
||||
tabContents->ReplaceLayoutParams(new AnchorLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
|
||||
// Will be filled in later.
|
||||
tabTweens_.push_back(nullptr);
|
||||
// This entry doesn't need one.
|
||||
createFuncs_.push_back(nullptr);
|
||||
}
|
||||
|
||||
void TabHolder::AddTabDeferred(std::string_view title, std::function<ViewGroup *()> createCb) {
|
||||
tabs_.push_back(nullptr); // marker
|
||||
tabStrip_->AddChoice(title);
|
||||
tabTweens_.push_back(nullptr);
|
||||
createFuncs_.push_back(createCb);
|
||||
|
||||
// Pre-create the first tab in a non-deferred way.
|
||||
if (tabs_.size() == 1) {
|
||||
EnsureTab(0);
|
||||
}
|
||||
}
|
||||
|
||||
void TabHolder::EnsureAllCreated() {
|
||||
for (int i = 0; i < createFuncs_.size(); i++) {
|
||||
if (createFuncs_[i]) {
|
||||
EnsureTab(i);
|
||||
tabs_[i]->SetVisibility(i == currentTab_ ? V_VISIBLE : V_GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TabHolder::EnsureTab(int index) {
|
||||
_dbg_assert_(index >= 0 && index < createFuncs_.size());
|
||||
|
||||
if (!tabs_[index]) {
|
||||
_dbg_assert_(index < createFuncs_.size());
|
||||
_dbg_assert_(createFuncs_[index]);
|
||||
std::function<UI::ViewGroup * ()> func;
|
||||
createFuncs_[index].swap(func);
|
||||
|
||||
ViewGroup *tabContents = func();
|
||||
tabs_[index] = tabContents;
|
||||
contents_->Add(tabContents);
|
||||
|
||||
tabContents->ReplaceLayoutParams(new AnchorLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
}
|
||||
}
|
||||
|
||||
void TabHolder::SetCurrentTab(int tab, bool skipTween) {
|
||||
|
@ -1008,7 +1054,10 @@ void TabHolder::SetCurrentTab(int tab, bool skipTween) {
|
|||
return;
|
||||
}
|
||||
|
||||
EnsureTab(tab);
|
||||
|
||||
auto setupTween = [&](View *view, AnchorTranslateTween *&tween) {
|
||||
_dbg_assert_(view != nullptr);
|
||||
if (tween)
|
||||
return;
|
||||
|
||||
|
@ -1051,6 +1100,7 @@ void TabHolder::SetCurrentTab(int tab, bool skipTween) {
|
|||
tabs_[tab]->SetVisibility(V_VISIBLE);
|
||||
|
||||
currentTab_ = tab;
|
||||
EnsureTab(currentTab_);
|
||||
}
|
||||
tabStrip_->SetSelection(tab, false);
|
||||
}
|
||||
|
@ -1059,6 +1109,7 @@ EventReturn TabHolder::OnTabClick(EventParams &e) {
|
|||
// We have e.b set when it was an explicit click action.
|
||||
// In that case, we make the view gone and then visible - this scrolls scrollviews to the top.
|
||||
if (e.b != 0) {
|
||||
EnsureTab(e.a);
|
||||
SetCurrentTab((int)e.a);
|
||||
}
|
||||
return EVENT_DONE;
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
|
||||
void Clear();
|
||||
void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) override;
|
||||
View *GetViewByIndex(int index) { return views_[index]; }
|
||||
View *GetViewByIndex(int index) const { return views_[index]; }
|
||||
int GetNumSubviews() const { return (int)views_.size(); }
|
||||
void SetHasDropShadow(bool has) { hasDropShadow_ = has; }
|
||||
void SetDropShadowExpand(float s) { dropShadowExpand_ = s; }
|
||||
|
@ -291,13 +291,14 @@ private:
|
|||
|
||||
class TabHolder : public LinearLayout {
|
||||
public:
|
||||
TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0);
|
||||
TabHolder(Orientation orientation, float stripSize, View *bannerView, LayoutParams *layoutParams = 0);
|
||||
|
||||
template <class T>
|
||||
T *AddTab(std::string_view title, T *tabContents) {
|
||||
AddTabContents(title, (View *)tabContents);
|
||||
AddTabContents(title, tabContents);
|
||||
return tabContents;
|
||||
}
|
||||
void AddTabDeferred(std::string_view title, std::function<ViewGroup *()> createCb);
|
||||
void EnableTab(int tab, bool enabled) {
|
||||
tabStrip_->EnableChoice(tab, enabled);
|
||||
}
|
||||
|
@ -311,20 +312,29 @@ public:
|
|||
|
||||
void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) override;
|
||||
|
||||
void EnsureAllCreated();
|
||||
|
||||
LinearLayout *Container() { return tabContainer_; }
|
||||
|
||||
private:
|
||||
void AddTabContents(std::string_view title, View *tabContents);
|
||||
EventReturn OnTabClick(EventParams &e);
|
||||
const std::vector<ViewGroup *> &GetTabContentViews() const {
|
||||
return tabs_;
|
||||
}
|
||||
|
||||
private:
|
||||
void AddTabContents(std::string_view title, ViewGroup *tabContents);
|
||||
EventReturn OnTabClick(EventParams &e);
|
||||
void EnsureTab(int index);
|
||||
|
||||
View *bannerView_ = nullptr;
|
||||
LinearLayout *tabContainer_ = nullptr;
|
||||
ChoiceStrip *tabStrip_ = nullptr;
|
||||
ScrollView *tabScroll_ = nullptr;
|
||||
AnchorLayout *contents_ = nullptr;
|
||||
ViewGroup *contents_ = nullptr;
|
||||
|
||||
int currentTab_ = 0;
|
||||
std::vector<View *> tabs_;
|
||||
std::vector<ViewGroup *> tabs_;
|
||||
std::vector<AnchorTranslateTween *> tabTweens_;
|
||||
std::vector<std::function<ViewGroup *()>> createFuncs_;
|
||||
};
|
||||
|
||||
class CollapsibleHeader;
|
||||
|
|
|
@ -1351,7 +1351,7 @@ PPGeImage::PPGeImage(std::string_view pspFilename)
|
|||
|
||||
PPGeImage::PPGeImage(u32 pngPointer, size_t pngSize)
|
||||
: filename_(""), png_(pngPointer), size_(pngSize) {
|
||||
if (!Memory::IsValidRange(this->png_, this->size_)) {
|
||||
if (!Memory::IsValidRange(this->png_, (u32)this->size_)) {
|
||||
WARN_LOG(Log::sceGe, "Created PPGeImage from invalid memory range %08x (%08x bytes). Will not be drawn.");
|
||||
}
|
||||
}
|
||||
|
@ -1417,7 +1417,7 @@ bool PPGeImage::IsValid() {
|
|||
if (loadFailed_)
|
||||
return false;
|
||||
|
||||
if (!Memory::IsValidRange(this->png_, this->size_)) {
|
||||
if (!Memory::IsValidRange(this->png_, (u32)this->size_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -523,9 +523,44 @@ void SystemInfoScreen::CreateTabs() {
|
|||
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
|
||||
LinearLayout *deviceSpecs = AddTab("Device Info", si->T("Device Info"));
|
||||
AddTab("Device Info", si->T("Device Info"), [this](UI::LinearLayout *parent) {
|
||||
CreateDeviceInfoTab(parent);
|
||||
});
|
||||
AddTab("Storage", si->T("Storage"), [this](UI::LinearLayout *parent) {
|
||||
CreateStorageTab(parent);
|
||||
});
|
||||
AddTab("DevSystemInfoBuildConfig", si->T("Build Config"), [this](UI::LinearLayout *parent) {
|
||||
CreateBuildConfigTab(parent);
|
||||
});
|
||||
AddTab("DevSystemInfoCPUExt", si->T("CPU Extensions"), [this](UI::LinearLayout *parent) {
|
||||
CreateCPUExtensionsTab(parent);
|
||||
});
|
||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
||||
AddTab("DevSystemInfoOGLExt", si->T("OGL Extensions"), [this](UI::LinearLayout *parent) {
|
||||
CreateOpenGLExtsTab(parent);
|
||||
});
|
||||
} else if (GetGPUBackend() == GPUBackend::VULKAN) {
|
||||
AddTab("DevSystemInfoVulkanExt", si->T("Vulkan Extensions"), [this](UI::LinearLayout *parent) {
|
||||
CreateVulkanExtsTab(parent);
|
||||
});
|
||||
}
|
||||
AddTab("DevSystemInfoDriverBugs", si->T("Driver bugs"), [this](UI::LinearLayout *parent) {
|
||||
CreateDriverBugsTab(parent);
|
||||
});
|
||||
AddTab("DevSystemInfoInternals", si->T("Internals"), [this](UI::LinearLayout *parent) {
|
||||
CreateInternalsTab(parent);
|
||||
});
|
||||
}
|
||||
|
||||
CollapsibleSection *systemInfo = deviceSpecs->Add(new CollapsibleSection(si->T("System Information")));
|
||||
void SystemInfoScreen::CreateDeviceInfoTab(UI::LinearLayout *deviceSpecs) {
|
||||
using namespace Draw;
|
||||
using namespace UI;
|
||||
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
|
||||
UI::CollapsibleSection *systemInfo = deviceSpecs->Add(new UI::CollapsibleSection(si->T("System Information")));
|
||||
|
||||
systemInfo->Add(new Choice(si->T("Copy summary to clipboard")))->OnClick.Handle(this, &SystemInfoScreen::CopySummaryToClipboard);
|
||||
systemInfo->Add(new InfoItem(si->T("System Name", "Name"), System_GetProperty(SYSPROP_NAME)));
|
||||
|
@ -546,7 +581,7 @@ void SystemInfoScreen::CreateTabs() {
|
|||
systemInfo->Add(new InfoItem(si->T("Debugger Present"), di->T("Yes")));
|
||||
}
|
||||
|
||||
CollapsibleSection *cpuInfo = deviceSpecs->Add(new CollapsibleSection(si->T("CPU Information")));
|
||||
UI::CollapsibleSection *cpuInfo = deviceSpecs->Add(new UI::CollapsibleSection(si->T("CPU Information")));
|
||||
|
||||
// Don't bother showing the CPU name if we don't have one.
|
||||
if (strcmp(cpu_info.brand_string, "Unknown") != 0) {
|
||||
|
@ -721,8 +756,12 @@ void SystemInfoScreen::CreateTabs() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinearLayout *storage = AddTab("Storage", si->T("Storage"));
|
||||
void SystemInfoScreen::CreateStorageTab(UI::LinearLayout *storage) {
|
||||
using namespace UI;
|
||||
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
|
||||
storage->Add(new ItemHeader(si->T("Directories")));
|
||||
// Intentionally non-translated
|
||||
|
@ -732,6 +771,7 @@ void SystemInfoScreen::CreateTabs() {
|
|||
storage->Add(new InfoItem("DefaultCurrentDir", g_Config.defaultCurrentDirectory.ToVisualString()));
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
storage->Add(new InfoItem("ExtFilesDir", g_extFilesDir));
|
||||
bool scoped = System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE);
|
||||
storage->Add(new InfoItem("Scoped Storage", scoped ? di->T("Yes") : di->T("No")));
|
||||
|
@ -740,8 +780,12 @@ void SystemInfoScreen::CreateTabs() {
|
|||
storage->Add(new InfoItem("IsStoragePreservedLegacy", Android_IsExternalStoragePreservedLegacy() ? di->T("Yes") : di->T("No")));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
LinearLayout *buildConfig = AddTab("DevSystemInfoBuildConfig", si->T("Build Config"));
|
||||
void SystemInfoScreen::CreateBuildConfigTab(UI::LinearLayout *buildConfig) {
|
||||
using namespace UI;
|
||||
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
|
||||
buildConfig->Add(new ItemHeader(si->T("Build Configuration")));
|
||||
#ifdef ANDROID_LEGACY
|
||||
|
@ -773,17 +817,28 @@ void SystemInfoScreen::CreateTabs() {
|
|||
if (System_GetPropertyBool(SYSPROP_APP_GOLD)) {
|
||||
buildConfig->Add(new InfoItem("GOLD", ""));
|
||||
}
|
||||
}
|
||||
|
||||
void SystemInfoScreen::CreateCPUExtensionsTab(UI::LinearLayout *cpuExtensions) {
|
||||
using namespace UI;
|
||||
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
|
||||
LinearLayout *cpuExtensions = AddTab("DevSystemInfoCPUExt", si->T("CPU Extensions"));
|
||||
cpuExtensions->Add(new ItemHeader(si->T("CPU Extensions")));
|
||||
std::vector<std::string> exts = cpu_info.Features();
|
||||
for (std::string &ext : exts) {
|
||||
cpuExtensions->Add(new TextView(ext, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
}
|
||||
|
||||
LinearLayout *driverBugs = AddTab("DevSystemInfoDriverBugs", si->T("Driver bugs"));
|
||||
void SystemInfoScreen::CreateDriverBugsTab(UI::LinearLayout *driverBugs) {
|
||||
using namespace UI;
|
||||
using namespace Draw;
|
||||
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
|
||||
bool anyDriverBugs = false;
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
for (int i = 0; i < (int)draw->GetBugs().MaxBugIndex(); i++) {
|
||||
if (draw->GetBugs().Has(i)) {
|
||||
anyDriverBugs = true;
|
||||
|
@ -794,90 +849,92 @@ void SystemInfoScreen::CreateTabs() {
|
|||
if (!anyDriverBugs) {
|
||||
driverBugs->Add(new TextView(si->T("No GPU driver bugs detected"), new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
||||
LinearLayout *gpuExtensions = AddTab("DevSystemInfoOGLExt", si->T("OGL Extensions"));
|
||||
void SystemInfoScreen::CreateOpenGLExtsTab(UI::LinearLayout *gpuExtensions) {
|
||||
using namespace UI;
|
||||
|
||||
if (!gl_extensions.IsGLES) {
|
||||
gpuExtensions->Add(new ItemHeader(si->T("OpenGL Extensions")));
|
||||
} else if (gl_extensions.GLES3) {
|
||||
gpuExtensions->Add(new ItemHeader(si->T("OpenGL ES 3.0 Extensions")));
|
||||
} else {
|
||||
gpuExtensions->Add(new ItemHeader(si->T("OpenGL ES 2.0 Extensions")));
|
||||
}
|
||||
exts.clear();
|
||||
SplitString(g_all_gl_extensions, ' ', exts);
|
||||
std::sort(exts.begin(), exts.end());
|
||||
for (auto &extension : exts) {
|
||||
gpuExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
|
||||
exts.clear();
|
||||
SplitString(g_all_egl_extensions, ' ', exts);
|
||||
std::sort(exts.begin(), exts.end());
|
||||
|
||||
// If there aren't any EGL extensions, no need to show the tab.
|
||||
if (exts.size() > 0) {
|
||||
LinearLayout *eglExtensions = AddTab("EglExt", si->T("EGL Extensions"));
|
||||
eglExtensions->SetSpacing(0);
|
||||
eglExtensions->Add(new ItemHeader(si->T("EGL Extensions")));
|
||||
for (auto &extension : exts) {
|
||||
eglExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
}
|
||||
} else if (GetGPUBackend() == GPUBackend::VULKAN) {
|
||||
LinearLayout *gpuExtensions = AddTab("DevSystemInfoOGLExt", si->T("Vulkan Features"));
|
||||
|
||||
CollapsibleSection *vulkanFeatures = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Features")));
|
||||
std::vector<std::string> features = draw->GetFeatureList();
|
||||
for (auto &feature : features) {
|
||||
vulkanFeatures->Add(new TextView(feature, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *presentModes = gpuExtensions->Add(new CollapsibleSection(si->T("Present modes")));
|
||||
for (auto mode : draw->GetPresentModeList(di->T("Current"))) {
|
||||
presentModes->Add(new TextView(mode, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *colorFormats = gpuExtensions->Add(new CollapsibleSection(si->T("Display Color Formats")));
|
||||
for (auto &format : draw->GetSurfaceFormatList()) {
|
||||
colorFormats->Add(new TextView(format, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *enabledExtensions = gpuExtensions->Add(new CollapsibleSection(std::string(si->T("Vulkan Extensions")) + " (" + std::string(di->T("Enabled")) + ")"));
|
||||
std::vector<std::string> extensions = draw->GetExtensionList(true, true);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
enabledExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
// Also get instance extensions
|
||||
enabledExtensions->Add(new ItemHeader(si->T("Instance")));
|
||||
extensions = draw->GetExtensionList(false, true);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
enabledExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *vulkanExtensions = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Extensions")));
|
||||
extensions = draw->GetExtensionList(true, false);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
vulkanExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
vulkanExtensions->Add(new ItemHeader(si->T("Instance")));
|
||||
// Also get instance extensions
|
||||
extensions = draw->GetExtensionList(false, false);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
vulkanExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
if (!gl_extensions.IsGLES) {
|
||||
gpuExtensions->Add(new ItemHeader(si->T("OpenGL Extensions")));
|
||||
} else if (gl_extensions.GLES3) {
|
||||
gpuExtensions->Add(new ItemHeader(si->T("OpenGL ES 3.0 Extensions")));
|
||||
} else {
|
||||
gpuExtensions->Add(new ItemHeader(si->T("OpenGL ES 2.0 Extensions")));
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
LinearLayout *internals = AddTab("DevSystemInfoInternals", si->T("Internals"));
|
||||
CreateInternalsTab(internals);
|
||||
#endif
|
||||
std::vector<std::string> exts;
|
||||
SplitString(g_all_gl_extensions, ' ', exts);
|
||||
std::sort(exts.begin(), exts.end());
|
||||
for (auto &extension : exts) {
|
||||
gpuExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
exts.clear();
|
||||
SplitString(g_all_egl_extensions, ' ', exts);
|
||||
std::sort(exts.begin(), exts.end());
|
||||
|
||||
// If there aren't any EGL extensions, no need to show the tab.
|
||||
gpuExtensions->Add(new ItemHeader(si->T("EGL Extensions")));
|
||||
for (auto &extension : exts) {
|
||||
gpuExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemInfoScreen::CreateVulkanExtsTab(UI::LinearLayout *gpuExtensions) {
|
||||
using namespace UI;
|
||||
|
||||
auto si = GetI18NCategory(I18NCat::SYSINFO);
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
|
||||
CollapsibleSection *vulkanFeatures = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Features")));
|
||||
std::vector<std::string> features = draw->GetFeatureList();
|
||||
for (const auto &feature : features) {
|
||||
vulkanFeatures->Add(new TextView(feature, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *presentModes = gpuExtensions->Add(new CollapsibleSection(si->T("Present modes")));
|
||||
for (const auto &mode : draw->GetPresentModeList(di->T("Current"))) {
|
||||
presentModes->Add(new TextView(mode, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *colorFormats = gpuExtensions->Add(new CollapsibleSection(si->T("Display Color Formats")));
|
||||
for (const auto &format : draw->GetSurfaceFormatList()) {
|
||||
colorFormats->Add(new TextView(format, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *enabledExtensions = gpuExtensions->Add(new CollapsibleSection(std::string(si->T("Vulkan Extensions")) + " (" + std::string(di->T("Enabled")) + ")"));
|
||||
std::vector<std::string> extensions = draw->GetExtensionList(true, true);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
enabledExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
// Also get instance extensions
|
||||
enabledExtensions->Add(new ItemHeader(si->T("Instance")));
|
||||
extensions = draw->GetExtensionList(false, true);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
enabledExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *vulkanExtensions = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Extensions")));
|
||||
extensions = draw->GetExtensionList(true, false);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
vulkanExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
vulkanExtensions->Add(new ItemHeader(si->T("Instance")));
|
||||
// Also get instance extensions
|
||||
extensions = draw->GetExtensionList(false, false);
|
||||
std::sort(extensions.begin(), extensions.end());
|
||||
for (auto &extension : extensions) {
|
||||
vulkanExtensions->Add(new TextView(extension, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemInfoScreen::CreateInternalsTab(UI::ViewGroup *internals) {
|
||||
|
@ -1007,7 +1064,7 @@ void ShaderListScreen::CreateViews() {
|
|||
LinearLayout *layout = new LinearLayout(ORIENT_VERTICAL);
|
||||
root_ = layout;
|
||||
|
||||
tabs_ = new TabHolder(ORIENT_HORIZONTAL, 40, new LinearLayoutParams(1.0));
|
||||
tabs_ = new TabHolder(ORIENT_HORIZONTAL, 40, nullptr, new LinearLayoutParams(1.0));
|
||||
tabs_->SetTag("DevShaderList");
|
||||
layout->Add(tabs_);
|
||||
layout->Add(new Button(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
|
||||
|
@ -1083,7 +1140,7 @@ void FrameDumpTestScreen::CreateViews() {
|
|||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
|
||||
TabHolder *tabHolder;
|
||||
tabHolder = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
tabHolder = new TabHolder(ORIENT_VERTICAL, 200, nullptr, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
root_->Add(tabHolder);
|
||||
AddStandardBack(root_);
|
||||
tabHolder->SetTag("DumpTypes");
|
||||
|
|
|
@ -115,7 +115,17 @@ public:
|
|||
protected:
|
||||
UI::EventReturn CopySummaryToClipboard(UI::EventParams &e);
|
||||
bool ShowSearchControls() const override { return false; }
|
||||
|
||||
private:
|
||||
void CreateDeviceInfoTab(UI::LinearLayout *deviceInfo);
|
||||
void CreateStorageTab(UI::LinearLayout *storage);
|
||||
void CreateBuildConfigTab(UI::LinearLayout *storage);
|
||||
void CreateCPUExtensionsTab(UI::LinearLayout *storage);
|
||||
void CreateDriverBugsTab(UI::LinearLayout *storage);
|
||||
void CreateInternalsTab(UI::ViewGroup *internals);
|
||||
void CreateOpenGLExtsTab(UI::LinearLayout *gpuExtensions);
|
||||
void CreateVulkanExtsTab(UI::LinearLayout *gpuExtensions);
|
||||
|
||||
};
|
||||
|
||||
class GPIGPOScreen : public PopupScreen {
|
||||
|
|
|
@ -152,8 +152,9 @@ void DriverManagerScreen::CreateTabs() {
|
|||
using namespace UI;
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
|
||||
LinearLayout *drivers = AddTab("DriverManagerDrivers", gr->T("Drivers"));
|
||||
CreateDriverTab(drivers);
|
||||
AddTab("DriverManagerDrivers", gr->T("Drivers"), [this](UI::LinearLayout *parent) {
|
||||
CreateDriverTab(parent);
|
||||
});
|
||||
}
|
||||
|
||||
void DriverManagerScreen::CreateDriverTab(UI::ViewGroup *drivers) {
|
||||
|
|
|
@ -212,10 +212,6 @@ EmuScreen::EmuScreen(const Path &filename)
|
|||
// Usually, we don't want focus movement enabled on this screen, so disable on start.
|
||||
// Only if you open chat or dev tools do we want it to start working.
|
||||
UI::EnableFocusMovement(false);
|
||||
|
||||
// TODO: Do this only on demand.
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
}
|
||||
|
||||
bool EmuScreen::bootAllowStorage(const Path &filename) {
|
||||
|
@ -460,7 +456,7 @@ void EmuScreen::bootComplete() {
|
|||
EmuScreen::~EmuScreen() {
|
||||
if (imguiInited_) {
|
||||
ImGui_ImplThin3d_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
ImGui::DestroyContext(ctx_);
|
||||
}
|
||||
|
||||
std::string gameID = g_paramSFO.GetValueString("DISC_ID");
|
||||
|
@ -1770,6 +1766,11 @@ void EmuScreen::runImDebugger() {
|
|||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
if (!imguiInited_) {
|
||||
imguiInited_ = true;
|
||||
|
||||
// TODO: Do this only on demand.
|
||||
IMGUI_CHECKVERSION();
|
||||
ctx_ = ImGui::CreateContext();
|
||||
|
||||
ImGui_ImplPlatform_Init(GetSysDirectory(DIRECTORY_SYSTEM) / "imgui.ini");
|
||||
imDebugger_ = std::make_unique<ImDebugger>();
|
||||
|
||||
|
|
|
@ -154,6 +154,8 @@ private:
|
|||
bool lastImguiEnabled_ = false;
|
||||
|
||||
std::vector<VirtKey> queuedVirtKeys_;
|
||||
|
||||
ImGuiContext *ctx_ = nullptr;
|
||||
};
|
||||
|
||||
bool MustRunBehind();
|
||||
|
|
|
@ -301,7 +301,7 @@ void GPUDriverTestScreen::CreateViews() {
|
|||
AnchorLayout *anchor = new AnchorLayout();
|
||||
root_ = anchor;
|
||||
|
||||
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 30.0f, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, false));
|
||||
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 30.0f, nullptr, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, false));
|
||||
anchor->Add(tabHolder_);
|
||||
tabHolder_->AddTab("Discard", new LinearLayout(ORIENT_VERTICAL));
|
||||
tabHolder_->AddTab("Shader", new LinearLayout(ORIENT_VERTICAL));
|
||||
|
|
|
@ -250,29 +250,37 @@ void GameSettingsScreen::CreateTabs() {
|
|||
using namespace UI;
|
||||
auto ms = GetI18NCategory(I18NCat::MAINSETTINGS);
|
||||
|
||||
LinearLayout *graphicsSettings = AddTab("GameSettingsGraphics", ms->T("Graphics"));
|
||||
CreateGraphicsSettings(graphicsSettings);
|
||||
AddTab("GameSettingsGraphics", ms->T("Graphics"), [this](UI::LinearLayout *parent) {
|
||||
CreateGraphicsSettings(parent);
|
||||
});
|
||||
|
||||
LinearLayout *controlsSettings = AddTab("GameSettingsControls", ms->T("Controls"));
|
||||
CreateControlsSettings(controlsSettings);
|
||||
AddTab("GameSettingsControls", ms->T("Controls"), [this](UI::LinearLayout *parent) {
|
||||
CreateControlsSettings(parent);
|
||||
});
|
||||
|
||||
LinearLayout *audioSettings = AddTab("GameSettingsAudio", ms->T("Audio"));
|
||||
CreateAudioSettings(audioSettings);
|
||||
AddTab("GameSettingsAudio", ms->T("Audio"), [this](UI::LinearLayout *parent) {
|
||||
CreateAudioSettings(parent);
|
||||
});
|
||||
|
||||
LinearLayout *networkingSettings = AddTab("GameSettingsNetworking", ms->T("Networking"));
|
||||
CreateNetworkingSettings(networkingSettings);
|
||||
AddTab("GameSettingsNetworking", ms->T("Networking"), [this](UI::LinearLayout *parent) {
|
||||
CreateNetworkingSettings(parent);
|
||||
});
|
||||
|
||||
LinearLayout *tools = AddTab("GameSettingsTools", ms->T("Tools"));
|
||||
CreateToolsSettings(tools);
|
||||
AddTab("GameSettingsTools", ms->T("Tools"), [this](UI::LinearLayout *parent) {
|
||||
CreateToolsSettings(parent);
|
||||
});
|
||||
|
||||
LinearLayout *systemSettings = AddTab("GameSettingsSystem", ms->T("System"));
|
||||
systemSettings->SetSpacing(0);
|
||||
CreateSystemSettings(systemSettings);
|
||||
AddTab("GameSettingsSystem", ms->T("System"), [this](UI::LinearLayout *parent) {
|
||||
parent->SetSpacing(0);
|
||||
CreateSystemSettings(parent);
|
||||
});
|
||||
|
||||
|
||||
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
|
||||
if ((deviceType == DEVICE_TYPE_VR) || g_Config.bForceVR) {
|
||||
LinearLayout *vrSettings = AddTab("GameSettingsVR", ms->T("VR"));
|
||||
CreateVRSettings(vrSettings);
|
||||
AddTab("GameSettingsVR", ms->T("VR"), [this](UI::LinearLayout *parent) {
|
||||
CreateVRSettings(parent);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2538,7 +2546,7 @@ void GestureMappingScreen::CreateViews() {
|
|||
|
||||
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
AddStandardBack(root_);
|
||||
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 200, nullptr, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
root_->Add(tabHolder);
|
||||
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
|
||||
tabHolder->AddTab(co->T("Gesture"), rightPanel);
|
||||
|
|
|
@ -1105,7 +1105,7 @@ void MainScreen::CreateViews() {
|
|||
|
||||
auto mm = GetI18NCategory(I18NCat::MAINMENU);
|
||||
|
||||
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 64, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
|
||||
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 64, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
|
||||
ViewGroup *leftColumn = tabHolder_;
|
||||
tabHolder_->SetTag("MainScreenGames");
|
||||
gameBrowsers_.clear();
|
||||
|
@ -1653,7 +1653,7 @@ void UmdReplaceScreen::CreateViews() {
|
|||
auto mm = GetI18NCategory(I18NCat::MAINMENU);
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
|
||||
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0));
|
||||
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0));
|
||||
leftColumn->SetTag("UmdReplace");
|
||||
leftColumn->SetClip(true);
|
||||
|
||||
|
|
|
@ -278,12 +278,14 @@ RemoteISOScreen::RemoteISOScreen(const Path &filename) : TabbedUIDialogScreenWit
|
|||
void RemoteISOScreen::CreateTabs() {
|
||||
auto ri = GetI18NCategory(I18NCat::REMOTEISO);
|
||||
|
||||
UI::LinearLayout *connect = AddTab("Connect", ri->T("Connect"));
|
||||
connect->SetSpacing(5.0f);
|
||||
CreateConnectTab(connect);
|
||||
AddTab("Connect", ri->T("Connect"), [this](UI::LinearLayout *connect) {
|
||||
connect->SetSpacing(5.0f);
|
||||
CreateConnectTab(connect);
|
||||
});
|
||||
|
||||
UI::LinearLayout *settings = AddTab("Settings", ri->T("Settings"));
|
||||
CreateSettingsTab(settings);
|
||||
AddTab("Settings", ri->T("Settings"), [this](UI::LinearLayout *settings) {
|
||||
CreateSettingsTab(settings);
|
||||
});
|
||||
}
|
||||
|
||||
void RemoteISOScreen::update() {
|
||||
|
@ -592,7 +594,7 @@ void RemoteISOBrowseScreen::CreateViews() {
|
|||
|
||||
bool vertical = UseVerticalLayout();
|
||||
|
||||
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
|
||||
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
|
||||
tabHolder_ = leftColumn;
|
||||
tabHolder_->SetTag("RemoteGames");
|
||||
gameBrowsers_.clear();
|
||||
|
|
|
@ -62,16 +62,21 @@ AudioFileChooser::AudioFileChooser(RequesterToken token, std::string *value, std
|
|||
void RetroAchievementsListScreen::CreateTabs() {
|
||||
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
|
||||
|
||||
UI::LinearLayout *achievements = AddTab("Achievements", ac->T("Achievements"));
|
||||
achievements->SetSpacing(5.0f);
|
||||
CreateAchievementsTab(achievements);
|
||||
AddTab("Achievements", ac->T("Achievements"), [this](UI::LinearLayout *parent) {
|
||||
parent->SetSpacing(5.0f);
|
||||
CreateAchievementsTab(parent);
|
||||
});
|
||||
|
||||
UI::LinearLayout *leaderboards = AddTab("Leaderboards", ac->T("Leaderboards"));
|
||||
leaderboards->SetSpacing(5.0f);
|
||||
CreateLeaderboardsTab(leaderboards);
|
||||
AddTab("Leaderboards", ac->T("Leaderboards"), [this](UI::LinearLayout *parent) {
|
||||
parent->SetSpacing(5.0f);
|
||||
CreateLeaderboardsTab(parent);
|
||||
});
|
||||
|
||||
#ifdef _DEBUG
|
||||
CreateStatisticsTab(AddTab("AchievementsStatistics", ac->T("Statistics")));
|
||||
AddTab("AchievementsStatistics", ac->T("Statistics"), [this](UI::LinearLayout *parent) {
|
||||
parent->SetSpacing(5.0f);
|
||||
CreateStatisticsTab(parent);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -200,7 +205,15 @@ void RetroAchievementsLeaderboardScreen::CreateTabs() {
|
|||
const rc_client_leaderboard_t *leaderboard = rc_client_get_leaderboard_info(Achievements::GetClient(), leaderboardID_);
|
||||
|
||||
using namespace UI;
|
||||
UI::LinearLayout *layout = AddTab("AchievementsLeaderboard", leaderboard->title);
|
||||
AddTab("AchievementsLeaderboard", leaderboard->title, [this, leaderboard](UI::LinearLayout *parent) {
|
||||
CreateLeaderboardTab(parent, leaderboard);
|
||||
});
|
||||
}
|
||||
|
||||
void RetroAchievementsLeaderboardScreen::CreateLeaderboardTab(UI::LinearLayout *layout, const rc_client_leaderboard_t *leaderboard) {
|
||||
using namespace UI;
|
||||
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
|
||||
|
||||
layout->Add(new TextView(leaderboard->description));
|
||||
layout->Add(new ItemHeader(ac->T("Leaderboard")));
|
||||
|
||||
|
@ -254,10 +267,16 @@ void RetroAchievementsSettingsScreen::CreateTabs() {
|
|||
|
||||
using namespace UI;
|
||||
|
||||
CreateAccountTab(AddTab("AchievementsAccount", ac->T("Account")));
|
||||
AddTab("AchievementsAccount", ac->T("Account"), [this](UI::LinearLayout *layout) {
|
||||
CreateAccountTab(layout);
|
||||
});
|
||||
// Don't bother creating this tab if we don't have a file browser.
|
||||
CreateCustomizeTab(AddTab("AchievementsCustomize", ac->T("Customize")));
|
||||
CreateDeveloperToolsTab(AddTab("AchievementsDeveloperTools", sy->T("Developer Tools")));
|
||||
AddTab("AchievementsCustomize", ac->T("Customize"), [this](UI::LinearLayout *layout) {
|
||||
CreateCustomizeTab(layout);
|
||||
});
|
||||
AddTab("AchievementsDeveloperTools", sy->T("Developer Tools"), [this](UI::LinearLayout *layout) {
|
||||
CreateDeveloperToolsTab(layout);
|
||||
});
|
||||
}
|
||||
|
||||
void RetroAchievementsSettingsScreen::sendMessage(UIMessage message, const char *value) {
|
||||
|
|
|
@ -66,6 +66,7 @@ protected:
|
|||
bool ShowSearchControls() const override { return false; }
|
||||
|
||||
private:
|
||||
void CreateLeaderboardTab(UI::LinearLayout *layout, const rc_client_leaderboard_t *leaderboard);
|
||||
void FetchEntries();
|
||||
void Poll();
|
||||
|
||||
|
|
|
@ -666,11 +666,13 @@ void SavedataScreen::CreateTabs() {
|
|||
using namespace UI;
|
||||
auto sa = GetI18NCategory(I18NCat::SAVEDATA);
|
||||
|
||||
LinearLayout *savedata = AddTab("SavedataBrowser", sa->T("Save Data"));
|
||||
CreateSavedataTab(savedata);
|
||||
AddTab("SavedataBrowser", sa->T("Save Data"), [this](UI::LinearLayout *parent) {
|
||||
CreateSavedataTab(parent);
|
||||
});
|
||||
|
||||
LinearLayout *savestate = AddTab("SavedataStatesBrowser", sa->T("Save States"));
|
||||
CreateSavestateTab(savestate);
|
||||
AddTab("SavedataStatesBrowser", sa->T("Save States"), [this](UI::LinearLayout *parent) {
|
||||
CreateSavestateTab(parent);
|
||||
});
|
||||
}
|
||||
|
||||
void SavedataScreen::CreateExtraButtons(UI::LinearLayout *verticalLayout, int margins) {
|
||||
|
|
|
@ -6,26 +6,18 @@
|
|||
#include "Common/System/Display.h"
|
||||
#include "UI/TabbedDialogScreen.h"
|
||||
|
||||
UI::LinearLayout *TabbedUIDialogScreenWithGameBackground::AddTab(const char *tag, std::string_view title, bool isSearch) {
|
||||
void TabbedUIDialogScreenWithGameBackground::AddTab(const char *tag, std::string_view title, std::function<void(UI::LinearLayout *)> createCallback, bool isSearch) {
|
||||
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 se = GetI18NCategory(I18NCat::SEARCH);
|
||||
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;
|
||||
tabHolder_->AddTabDeferred(title, [this, createCallback = std::move(createCallback), tag, title, isSearch]() -> UI::ViewGroup * {
|
||||
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);
|
||||
createCallback(contents);
|
||||
return scroll;
|
||||
});
|
||||
}
|
||||
|
||||
void TabbedUIDialogScreenWithGameBackground::CreateViews() {
|
||||
|
@ -40,16 +32,20 @@ void TabbedUIDialogScreenWithGameBackground::CreateViews() {
|
|||
|
||||
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
|
||||
auto se = GetI18NCategory(I18NCat::SEARCH);
|
||||
filterNotice_ = new TextView("(filter notice, you shouldn't see this text", new LinearLayoutParams(Margins(20, 5)));
|
||||
filterNotice_->SetVisibility(V_GONE);
|
||||
|
||||
if (vertical) {
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
LinearLayout *verticalLayout = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, new LinearLayoutParams(1.0f));
|
||||
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, filterNotice_, new LinearLayoutParams(1.0f));
|
||||
verticalLayout->Add(tabHolder_);
|
||||
CreateExtraButtons(verticalLayout, 0);
|
||||
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));
|
||||
tabHolder_ = new TabHolder(ORIENT_VERTICAL, 200, filterNotice_, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
CreateExtraButtons(tabHolder_->Container(), 10);
|
||||
tabHolder_->AddBack(this);
|
||||
root_->Add(tabHolder_);
|
||||
|
@ -57,8 +53,6 @@ void TabbedUIDialogScreenWithGameBackground::CreateViews() {
|
|||
|
||||
tabHolder_->SetTag(tag()); // take the tag from the screen.
|
||||
root_->SetDefaultFocusView(tabHolder_);
|
||||
settingTabContents_.clear();
|
||||
settingTabFilterNotices_.clear();
|
||||
|
||||
float leftSide = 40.0f;
|
||||
if (!vertical) {
|
||||
|
@ -81,26 +75,26 @@ void TabbedUIDialogScreenWithGameBackground::CreateViews() {
|
|||
// 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) && ShowSearchControls()) {
|
||||
auto se = GetI18NCategory(I18NCat::SEARCH);
|
||||
auto ms = GetI18NCategory(I18NCat::MAINSETTINGS);
|
||||
// Search
|
||||
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);
|
||||
auto ms = GetI18NCategory(I18NCat::MAINSETTINGS);
|
||||
AddTab("GameSettingsSearch", ms->T("Search"), [this](UI::LinearLayout *searchSettings) {
|
||||
auto se = GetI18NCategory(I18NCat::SEARCH);
|
||||
|
||||
searchSettings->Add(new ItemHeader(se->T("Find settings")));
|
||||
searchSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Add([=](UI::EventParams &e) {
|
||||
System_PostUIMessage(UIMessage::GAMESETTINGS_SEARCH, StripSpaces(searchFilter_));
|
||||
return UI::EVENT_DONE;
|
||||
});
|
||||
searchSettings->Add(new ItemHeader(se->T("Find settings")));
|
||||
searchSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Add([=](UI::EventParams &e) {
|
||||
System_PostUIMessage(UIMessage::GAMESETTINGS_SEARCH, StripSpaces(searchFilter_));
|
||||
return UI::EVENT_DONE;
|
||||
});
|
||||
|
||||
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
|
||||
clearSearchChoice_->OnClick.Add([=](UI::EventParams &e) {
|
||||
System_PostUIMessage(UIMessage::GAMESETTINGS_SEARCH, "");
|
||||
return UI::EVENT_DONE;
|
||||
});
|
||||
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
|
||||
clearSearchChoice_->OnClick.Add([=](UI::EventParams &e) {
|
||||
System_PostUIMessage(UIMessage::GAMESETTINGS_SEARCH, "");
|
||||
return UI::EVENT_DONE;
|
||||
});
|
||||
|
||||
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
|
||||
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
|
||||
}, true);
|
||||
|
||||
ApplySearchFilter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,16 +116,37 @@ void TabbedUIDialogScreenWithGameBackground::RecreateViews() {
|
|||
}
|
||||
|
||||
void TabbedUIDialogScreenWithGameBackground::ApplySearchFilter() {
|
||||
using namespace UI;
|
||||
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();
|
||||
tabHolder_->EnsureAllCreated();
|
||||
|
||||
// Show an indicator that a filter is applied.
|
||||
settingTabFilterNotices_[t]->SetVisibility(tabMatches ? UI::V_GONE : UI::V_VISIBLE);
|
||||
settingTabFilterNotices_[t]->SetText(ApplySafeSubstitutions(se->T("Filtering settings by '%1'"), searchFilter_));
|
||||
// Show an indicator that a filter is applied.
|
||||
filterNotice_->SetVisibility(searchFilter_.empty() ? UI::V_GONE : UI::V_VISIBLE);
|
||||
filterNotice_->SetText(ApplySafeSubstitutions(se->T("Filtering settings by '%1'"), searchFilter_));
|
||||
|
||||
bool matches = searchFilter_.empty();
|
||||
|
||||
const std::vector<ViewGroup *> settingTabs = tabHolder_->GetTabContentViews();
|
||||
|
||||
for (int t = 0; t < (int)settingTabs.size(); ++t) {
|
||||
const ViewGroup *tabContents = settingTabs[t];
|
||||
std::string_view tag = tabContents->Tag();
|
||||
|
||||
// Dive down to the actual list of settings.
|
||||
// TODO: Do this recursively instead.
|
||||
while (tabContents->GetNumSubviews() == 1) {
|
||||
View *v = tabContents->GetViewByIndex(0);
|
||||
if (v->IsViewGroup()) {
|
||||
tabContents = (ViewGroup *)v;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag == "GameSettingsSearch") {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool tabMatches = searchFilter_.empty();
|
||||
|
||||
UI::View *lastHeading = nullptr;
|
||||
for (int i = 1; i < tabContents->GetNumSubviews(); ++i) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#include <functional>
|
||||
|
||||
#include "Common/UI/UIScreen.h"
|
||||
#include "Common/System/System.h"
|
||||
|
@ -11,7 +12,7 @@ class TabbedUIDialogScreenWithGameBackground : public UIDialogScreenWithGameBack
|
|||
public:
|
||||
TabbedUIDialogScreenWithGameBackground(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) {}
|
||||
|
||||
UI::LinearLayout *AddTab(const char *tag, std::string_view title, bool isSearch = false);
|
||||
void AddTab(const char *tag, std::string_view title, std::function<void(UI::LinearLayout *)> createCallback, bool isSearch = false);
|
||||
void CreateViews() override;
|
||||
|
||||
protected:
|
||||
|
@ -30,10 +31,10 @@ private:
|
|||
void ApplySearchFilter();
|
||||
|
||||
UI::TabHolder *tabHolder_ = nullptr;
|
||||
std::vector<UI::LinearLayout *> settingTabContents_;
|
||||
std::vector<UI::TextView *> settingTabFilterNotices_;
|
||||
UI::TextView *filterNotice_ = nullptr;
|
||||
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_;
|
||||
|
|
|
@ -57,7 +57,7 @@ void TouchControlVisibilityScreen::CreateViews() {
|
|||
Choice *toggleAll = new Choice(di->T("Toggle All"), "", false, new AnchorLayoutParams(leftColumnWidth - 10, WRAP_CONTENT, 10, NONE, NONE, 84));
|
||||
root_->Add(toggleAll)->OnClick.Handle(this, &TouchControlVisibilityScreen::OnToggleAll);
|
||||
|
||||
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, nullptr, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
tabHolder->SetTag("TouchControlVisibility");
|
||||
root_->Add(tabHolder);
|
||||
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
|
||||
|
@ -144,7 +144,7 @@ void RightAnalogMappingScreen::CreateViews() {
|
|||
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
Choice *back = new Choice(di->T("Back"), "", false, new AnchorLayoutParams(leftColumnWidth - 10, WRAP_CONTENT, 10, NONE, NONE, 10));
|
||||
root_->Add(back)->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
|
||||
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, nullptr, new AnchorLayoutParams(10, 0, 10, 0, false));
|
||||
root_->Add(tabHolder);
|
||||
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
|
||||
tabHolder->AddTab(co->T("Binds"), rightPanel);
|
||||
|
|
Loading…
Add table
Reference in a new issue