Files
ppsspp/UI/SettingsPage.cpp
T
Henrik RydgårdandClaude Opus 5.5 2af86ed389 SettingsPage: Add the item types the other settings tabs need
Buttons, float sliders, slider steps and units, negative labels, a disabled
pointer, a separate category for choice names, and a setup callback for
one-off tweaks. CreateSettingView is now public, so single items can be
created (for search results), and CreateSettingViews can report the view
created for each item.

Also fixes the no-default slider assert, where NO_DEFAULT_INT was ambiguous
between the UI and config ones.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 14:45:17 +02:00

231 lines
7.3 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// This program 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, version 2.0 or later versions.
// This program 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Common/Log.h"
#include "Common/UI/View.h"
#include "Common/UI/ViewGroup.h"
#include "Common/UI/PopupScreens.h"
#include "Core/Config.h"
#include "UI/MiscViews.h"
#include "UI/SettingsPage.h"
std::string_view SettingText::Translate(I18NCat pageCat) const {
return T(hasCat ? cat : pageCat, key, def ? def : "");
}
std::string_view SettingText::English() const {
return def ? def : key;
}
SettingItem &SettingsPage::Add(SettingType type, SettingText text) {
SettingItem &item = items_.emplace_back();
item.type = type;
item.text = text;
return item;
}
SettingItem &SettingsPage::Header(SettingText text) {
return Add(SettingType::Header, text);
}
SettingItem &SettingsPage::Bool(bool *value, SettingText text) {
SettingItem &item = Add(SettingType::Bool, text);
item.ptr = value;
return item;
}
SettingItem &SettingsPage::IntChoice(int *value, SettingText text, const char **choices, int minVal, int numChoices) {
SettingItem &item = Add(SettingType::IntChoice, text);
item.ptr = value;
item.choices = choices;
item.minVal = minVal;
item.numChoices = numChoices;
return item;
}
SettingItem &SettingsPage::StringChoice(std::string *value, SettingText text, std::vector<std::string> names, std::vector<std::string> values) {
_dbg_assert_(values.empty() || values.size() == names.size());
SettingItem &item = Add(SettingType::StringChoice, text);
item.ptr = value;
item.choiceNames = std::move(names);
item.choiceValues = std::move(values);
return item;
}
SettingItem &SettingsPage::IntSlider(int *value, int minValue, int maxValue, SettingText text) {
SettingItem &item = Add(SettingType::IntSlider, text);
item.ptr = value;
item.minValue = minValue;
item.maxValue = maxValue;
return item;
}
SettingItem &SettingsPage::FloatSlider(float *value, float minValue, float maxValue, float defaultValue, float step, SettingText text) {
SettingItem &item = Add(SettingType::FloatSlider, text);
item.ptr = value;
item.fMinValue = minValue;
item.fMaxValue = maxValue;
item.fDefaultValue = defaultValue;
item.fStep = step;
return item;
}
SettingItem &SettingsPage::Choice(SettingText text, ImageID image) {
SettingItem &item = Add(SettingType::Choice, text);
item.image = image;
return item;
}
SettingItem &SettingsPage::Info(SettingText text, std::string_view rightText) {
SettingItem &item = Add(SettingType::Info, text);
item.rightText = rightText;
return item;
}
SettingItem &SettingsPage::Hint(SettingText text) {
_dbg_assert_(!items_.empty());
return Add(SettingType::Hint, text);
}
SettingItem &SettingsPage::Custom(SettingText text, std::function<UI::View *(UI::ViewGroup *parent)> create) {
SettingItem &item = Add(SettingType::Custom, text);
item.createCustom = std::move(create);
return item;
}
static UI::View *CreateSettingViewInner(const SettingItem &item, I18NCat pageCat, UI::View *prevView, UI::ViewGroup *parent, ScreenManager *screenManager) {
using namespace UI;
std::string_view text = item.text.Translate(pageCat);
switch (item.type) {
case SettingType::Header:
return parent->Add(new ItemHeader(text));
case SettingType::Bool:
{
CheckBox *checkBox = parent->Add(new CheckBox((bool *)item.ptr, text));
if (item.onChange) {
checkBox->OnClick.Add(item.onChange);
}
return checkBox;
}
case SettingType::IntChoice:
{
I18NCat choiceCat = item.hasChoiceCat ? item.choiceCat : (item.text.hasCat ? item.text.cat : pageCat);
PopupMultiChoice *choice = parent->Add(new PopupMultiChoice((int *)item.ptr, text, item.choices, item.minVal, item.numChoices, choiceCat, screenManager));
if (item.onChange) {
choice->OnChoice.Add(item.onChange);
}
return choice;
}
case SettingType::StringChoice:
{
// PopupMultiChoiceDynamic copies the values.
std::vector<std::string> values = item.choiceValues;
PopupMultiChoiceDynamic *choice = parent->Add(new PopupMultiChoiceDynamic((std::string *)item.ptr, text, item.choiceNames, I18NCat::NONE, screenManager, values.empty() ? nullptr : &values));
if (item.onChange) {
choice->OnChoice.Add(item.onChange);
}
return choice;
}
case SettingType::IntSlider:
{
int defaultValue = item.defaultValue;
if (!item.hasDefault) {
defaultValue = Config::GetDefaultValueInt((int *)item.ptr);
_dbg_assert_msg_(defaultValue != ::NO_DEFAULT_INT, "No default for slider '%s'", item.text.key);
}
PopupSliderChoice *slider = parent->Add(new PopupSliderChoice((int *)item.ptr, item.minValue, item.maxValue, defaultValue, text, item.step, screenManager, item.units));
if (!item.format.empty()) {
slider->SetFormat(item.format);
}
if (!item.zeroLabel.empty()) {
slider->SetZeroLabel(item.zeroLabel.Translate(pageCat));
}
if (!item.negativeLabel.empty()) {
slider->SetNegativeDisable(item.negativeLabel);
}
if (item.liveUpdate) {
slider->SetLiveUpdate(true);
}
if (item.restrictTo) {
slider->RestrictChoices(item.restrictTo, item.restrictCount);
}
if (item.onChange) {
slider->OnChange.Add(item.onChange);
}
return slider;
}
case SettingType::FloatSlider:
{
PopupSliderChoiceFloat *slider = parent->Add(new PopupSliderChoiceFloat((float *)item.ptr, item.fMinValue, item.fMaxValue, item.fDefaultValue, text, item.fStep, screenManager, item.units));
if (item.liveUpdate) {
slider->SetLiveUpdate(true);
}
if (item.onChange) {
slider->OnChange.Add(item.onChange);
}
return slider;
}
case SettingType::Choice:
{
UI::Choice *choice = parent->Add(new UI::Choice(text, item.image));
if (item.onChange) {
choice->OnClick.Add(item.onChange);
}
return choice;
}
case SettingType::Info:
return parent->Add(new InfoItem(text, item.rightText));
case SettingType::Hint:
return parent->Add(new SettingHint(text, prevView));
case SettingType::Custom:
return item.createCustom(parent);
}
return nullptr;
}
UI::View *CreateSettingView(const SettingItem &item, I18NCat pageCat, UI::View *prevView, UI::ViewGroup *parent, ScreenManager *screenManager) {
UI::View *view = CreateSettingViewInner(item, pageCat, prevView, parent, screenManager);
if (!view) {
return nullptr;
}
if (item.enabledFunc) {
view->SetEnabledFunc(item.enabledFunc);
} else if (item.enabledPtr) {
view->SetEnabledPtr(item.enabledPtr);
} else if (item.disabledPtr) {
view->SetDisabledPtr(item.disabledPtr);
}
if (item.setup) {
item.setup(view);
}
return view;
}
void CreateSettingViews(const SettingsPage &page, UI::ViewGroup *parent, ScreenManager *screenManager, std::vector<UI::View *> *views) {
UI::View *prevView = nullptr;
for (const SettingItem &item : page.Items()) {
UI::View *view = CreateSettingView(item, page.DefaultCat(), prevView, parent, screenManager);
if (views) {
views->push_back(view);
}
if (view) {
prevView = view;
}
}
}