UI: Allow a custom why-disabled message on views and setting items

View::SetDisabledReason, and SettingItem::DisabledReason for settings
pages. When set, it's shown instead of the message worked out from the
enabled pointer, and it also works for items with enabled callbacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-11-05 11:58:36 +01:00
1 parent 6f709515e3
commit 1cb9b1d3ef
3 files changed
+18 -2

No files matched your search

+5
View File
@@ -478,6 +478,10 @@ public:
*meansDisabled = enabledMeansDisabled_;
return enabledPtr_;
}
// Shown when the user tries to activate the view while it's disabled, instead of the
// message worked out from the enabled pointer (see SetDisabledActivationCallback).
void SetDisabledReason(std::string_view reason) { disabledReason_ = reason; }
const std::string &GetDisabledReason() const { return disabledReason_; }
virtual void SetVisibility(Visibility visibility) { visibility_ = visibility; }
Visibility GetVisibility() const { return visibility_; }
@@ -544,6 +548,7 @@ private:
bool enabled_ = true;
bool enabledMeansDisabled_ = false;
bool alwaysVisibleInSearch_ = false;
std::string disabledReason_;
DISALLOW_COPY_AND_ASSIGN(View);
};
+7
View File
@@ -71,6 +71,10 @@ static SettingText LabelText(const ConfigSettingInfo &info) {
}
void ShowWhyViewDisabled(UI::View *view) {
if (!view->GetDisabledReason().empty()) {
g_OSD.Show(OSDType::MESSAGE_INFO, view->GetDisabledReason(), 0.0f, "disabledsetting");
return;
}
bool meansDisabled = false;
const bool *ptr = view->GetEnabledPtr(&meansDisabled);
if (!ptr) {
@@ -413,6 +417,9 @@ static UI::View *CreateSettingView(const SettingItem &item, I18NCat pageCat, UI:
} else if (item.disabledPtr) {
view->SetDisabledPtr(item.disabledPtr);
}
if (!item.disabledReason.empty()) {
view->SetDisabledReason(item.disabledReason.Translate(pageCat));
}
if (item.opensScreen) {
if (UI::Choice *choice = dynamic_cast<UI::Choice *>(view)) {
choice->SetIconRight(ImageID("I_CHEVRON_RIGHT"));
+6 -2
View File
@@ -153,6 +153,7 @@ struct SettingItem {
bool *enabledPtr = nullptr;
bool *disabledPtr = nullptr;
std::function<bool()> enabledFunc;
SettingText disabledReason;
// Called on click (Bool, Choice), choice (choices) or change (sliders).
std::function<void(UI::EventParams &)> onChange;
// From the config, for settings described there. Called before onChange.
@@ -167,6 +168,8 @@ struct SettingItem {
SettingItem &Enabled(bool *ptr) { enabledPtr = ptr; return *this; }
SettingItem &Disabled(bool *ptr) { disabledPtr = ptr; return *this; }
SettingItem &EnabledFunc(std::function<bool()> func) { enabledFunc = std::move(func); return *this; }
// Shown when the user tries to use the item while it's disabled (see ShowWhyViewDisabled).
SettingItem &DisabledReason(SettingText text) { disabledReason = text; return *this; }
SettingItem &OnChange(std::function<void(UI::EventParams &)> func) { onChange = std::move(func); return *this; }
SettingItem &OnClick(std::function<void(UI::EventParams &)> func) { onChange = std::move(func); return *this; }
SettingItem &Setup(std::function<void(UI::View *)> func) { setup = std::move(func); return *this; }
@@ -223,8 +226,9 @@ private:
};
// If views is set, it gets the view created for each item (or null), in the same order.
// Explains in an OSD message which setting has to be on or off for a disabled view to be usable,
// if it's disabled by one (SetEnabledPtr or SetDisabledPtr on a config setting).
// Explains in an OSD message why a disabled view can't be used: its SetDisabledReason text if it
// has one, otherwise which setting has to be on or off, if it's disabled by one (SetEnabledPtr or
// SetDisabledPtr on a config setting).
void ShowWhyViewDisabled(UI::View *view);
void CreateSettingViews(const SettingsPage &page, UI::ViewGroup *parent, ScreenManager *screenManager, std::vector<UI::View *> *views = nullptr);