Add a way to put the "ExtraButtons" in a popup menu, use on control mapping screen

This commit is contained in:
Henrik Rydgård
2025-11-11 12:30:22 +01:00
parent 09d195c9ef
commit 8b52cf67af
16 changed files with 71 additions and 19 deletions
+7
View File
@@ -267,6 +267,13 @@ void PopupContextMenuScreen::CreatePopupContents(UI::ViewGroup *parent) {
ap->top = sourceView_->GetBounds().y2();
}
void PopupCallbackScreen::CreatePopupContents(ViewGroup *parent) {
createViews_(parent);
for (int i = 0; i < parent->GetNumSubviews(); i++) {
parent->GetViewByIndex(i)->SetAutoResult(DialogResult::DR_OK);
}
}
std::string ChopTitle(const std::string &title) {
size_t pos = title.find('\n');
if (pos != title.npos) {
+16 -1
View File
@@ -241,7 +241,6 @@ struct ContextMenuItem {
class PopupContextMenuScreen : public PopupScreen {
public:
PopupContextMenuScreen(const ContextMenuItem *items, size_t itemCount, I18NCat category, UI::View *sourceView);
void CreatePopupContents(ViewGroup *parent) override;
const char *tag() const override { return "ContextMenuPopup"; }
@@ -252,6 +251,7 @@ public:
UI::Event OnChoice;
private:
void CreatePopupContents(ViewGroup *parent) override;
const ContextMenuItem *items_;
size_t itemCount_;
I18NCat category_;
@@ -259,6 +259,21 @@ private:
std::vector<bool> enabled_;
};
class PopupCallbackScreen : public PopupScreen {
public:
PopupCallbackScreen(std::function<void(UI::ViewGroup *)> createViews, UI::View *sourceView) : PopupScreen(""), createViews_(createViews) {
if (sourceView) {
SetPopupOrigin(sourceView);
}
}
const char *tag() const override { return "ContextMenuPopup"; }
private:
void CreatePopupContents(ViewGroup *parent) override;
std::function<void(UI::ViewGroup *)> createViews_;
};
// Reads and writes value to determine the current selection.
class PopupMultiChoice : public AbstractChoiceWithValueDisplay {
public:
+8 -1
View File
@@ -8,7 +8,7 @@
namespace UI {
TabHolder::TabHolder(Orientation orientation, float stripSize, TabHolderFlags flags, View *bannerView, LayoutParams *layoutParams)
TabHolder::TabHolder(Orientation orientation, float stripSize, TabHolderFlags flags, View *bannerView, std::function<void()> contextMenuCallback, LayoutParams *layoutParams)
: LinearLayout(Opposite(orientation), layoutParams), tabOrientation_(orientation), flags_(flags) {
SetSpacing(0.0f);
if (orientation == ORIENT_HORIZONTAL) {
@@ -26,6 +26,13 @@ TabHolder::TabHolder(Orientation orientation, float stripSize, TabHolderFlags fl
tabScroll_ = new ScrollView(orientation, new LinearLayoutParams(1.0f));
tabScroll_->Add(tabStrip_);
container->Add(tabScroll_);
if (contextMenuCallback) {
Choice *menuChoice = new Choice(ImageID("I_THREE_DOTS"), new LinearLayoutParams(ITEM_HEIGHT, ITEM_HEIGHT));
menuChoice->OnClick.Add([contextMenuCallback](EventParams &e) {
contextMenuCallback();
});
container->Add(menuChoice);
}
Add(container);
} else {
tabScroll_ = new ScrollView(orientation, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
+1 -1
View File
@@ -21,7 +21,7 @@ ENUM_CLASS_BITOPS(TabHolderFlags);
class TabHolder : public LinearLayout {
public:
TabHolder(Orientation orientation, float stripSize, TabHolderFlags flags, View *bannerView, LayoutParams *layoutParams);
TabHolder(Orientation orientation, float stripSize, TabHolderFlags flags, View *bannerView, std::function<void()> contextMenuCallback, LayoutParams *layoutParams);
template <class T>
T *AddTab(std::string_view title, ImageID imageId, T *tabContents) {
+3
View File
@@ -221,6 +221,9 @@ void Clickable::DrawBG(UIContext &dc, const Style &style) {
void Clickable::ClickInternal() {
UI::EventParams e{};
e.v = this;
if (hasAutoResult_) {
e.bubbleResult = autoResult_;
}
OnClick.Trigger(e);
};
+9 -1
View File
@@ -463,6 +463,10 @@ public:
}
virtual void Recurse(void (*func)(View *view)) {}
virtual void SetAutoResult(DialogResult result) {
hasAutoResult_ = true;
autoResult_ = result;
}
protected:
// Inputs to layout
@@ -482,6 +486,8 @@ protected:
// Whether to use popup colors for styling.
bool popupStyle_ = false;
bool hasAutoResult_ = false;
DialogResult autoResult_ = DR_OK;
private:
std::function<bool()> enabledFunc_;
@@ -893,6 +899,9 @@ public:
virtual void Toggle();
virtual bool Toggled() const;
// we don't allow these for checkboxes.
virtual void SetAutoResult(DialogResult result) {}
protected:
void ClickInternal() override;
@@ -998,7 +1007,6 @@ private:
bool big_ = false;
};
class TextView : public InertView {
public:
TextView(std::string_view text, LayoutParams *layoutParams = 0)
+1 -1
View File
@@ -232,7 +232,7 @@ static const BindingCategory cats[] = {
{}, // sentinel
};
void ControlMappingScreen::CreateExtraButtons(UI::LinearLayout *verticalLayout, int margins) {
void ControlMappingScreen::CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) {
using namespace UI;
auto km = GetI18NCategory(I18NCat::KEYMAPPING);
verticalLayout->Add(new Choice(km->T("Clear All")))->OnClick.Add([](UI::EventParams &) {
+2 -2
View File
@@ -39,7 +39,7 @@ class SingleControlMapper;
class ControlMappingScreen : public UITabbedBaseDialogScreen {
public:
ControlMappingScreen(const Path &gamePath) : UITabbedBaseDialogScreen(gamePath) {
ControlMappingScreen(const Path &gamePath) : UITabbedBaseDialogScreen(gamePath, TabDialogFlags::ContextMenuInPortrait) {
categoryToggles_[0] = true;
categoryToggles_[1] = true;
categoryToggles_[2] = true;
@@ -49,7 +49,7 @@ public:
protected:
void CreateTabs() override;
void CreateExtraButtons(UI::LinearLayout *verticalLayout, int margins) override;
void CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) override;
void update() override;
private:
+1 -1
View File
@@ -301,7 +301,7 @@ void GPUDriverTestScreen::CreateViews() {
AnchorLayout *anchor = new AnchorLayout();
root_ = anchor;
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 30.0f, TabHolderFlags::Default, nullptr, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, Centering::None));
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 30.0f, TabHolderFlags::Default, nullptr, nullptr, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, Centering::None));
anchor->Add(tabHolder_);
tabHolder_->AddTab("Discard", ImageID::invalid(), new LinearLayout(ORIENT_VERTICAL));
tabHolder_->AddTab("Shader", ImageID::invalid(), new LinearLayout(ORIENT_VERTICAL));
+2 -2
View File
@@ -1224,7 +1224,7 @@ void MainScreen::CreateViews() {
auto mm = GetI18NCategory(I18NCat::MAINMENU);
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 64, TabHolderFlags::Default, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 64, TabHolderFlags::Default, nullptr, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
ViewGroup *leftColumn = tabHolder_;
tabHolder_->SetTag("MainScreenGames");
gameBrowsers_.clear();
@@ -1610,7 +1610,7 @@ void UmdReplaceScreen::CreateViews() {
const bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait;
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, TabHolderFlags::Default, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0));
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, TabHolderFlags::Default, nullptr, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0));
leftColumn->SetTag("UmdReplace");
leftColumn->SetClip(true);
+1 -1
View File
@@ -596,7 +596,7 @@ void RemoteISOBrowseScreen::CreateViews() {
using namespace UI;
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, TabHolderFlags::Default, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, TabHolderFlags::Default, nullptr, nullptr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
tabHolder_ = leftColumn;
tabHolder_->SetTag("RemoteGames");
gameBrowsers_.clear();
+1 -1
View File
@@ -671,7 +671,7 @@ void SavedataScreen::CreateTabs() {
});
}
void SavedataScreen::CreateExtraButtons(UI::LinearLayout *verticalLayout, int margins) {
void SavedataScreen::CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) {
using namespace UI;
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
auto di = GetI18NCategory(I18NCat::DIALOG);
+2 -2
View File
@@ -80,10 +80,10 @@ public:
protected:
void CreateTabs() override;
void CreateExtraButtons(UI::LinearLayout *verticalLayout, int margins) override;
void CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) override;
bool ShowSearchControls() const override { return false; }
private:
void OnSavedataButtonClick(UI::EventParams &e);
void OnSearch(UI::EventParams &e);
+13 -3
View File
@@ -58,16 +58,26 @@ void UITabbedBaseDialogScreen::CreateViews() {
if (flags_ & TabDialogFlags::HorizontalOnlyIcons) {
tabHolderFlags |= TabHolderFlags::HorizontalOnlyIcons;
}
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, tabHolderFlags, filterNotice_, new LinearLayoutParams(1.0f));
std::function<void()> contextMenu;
if (flags_ & TabDialogFlags::ContextMenuInPortrait) {
contextMenu = [this]() {
this->screenManager()->push(new PopupCallbackScreen([this](UI::ViewGroup *parent) {
CreateExtraButtons(parent, 0);
}, nullptr));
};
}
tabHolder_ = new TabHolder(ORIENT_HORIZONTAL, 200, tabHolderFlags, filterNotice_, contextMenu, new LinearLayoutParams(1.0f));
verticalLayout->Add(tabHolder_);
CreateExtraButtons(verticalLayout, 0);
if (!(flags_ & TabDialogFlags::ContextMenuInPortrait)) {
CreateExtraButtons(verticalLayout, 0);
}
root_->Add(verticalLayout);
} else {
TabHolderFlags tabHolderFlags = TabHolderFlags::Default;
if (flags_ & TabDialogFlags::VerticalShowIcons) {
tabHolderFlags |= TabHolderFlags::VerticalShowIcons;
}
tabHolder_ = new TabHolder(ORIENT_VERTICAL, 300, tabHolderFlags, filterNotice_, new AnchorLayoutParams(10, 0, 10, 0));
tabHolder_ = new TabHolder(ORIENT_VERTICAL, 300, tabHolderFlags, filterNotice_, nullptr, new AnchorLayoutParams(10, 0, 10, 0));
CreateExtraButtons(tabHolder_->Container(), 10);
tabHolder_->AddBack(this);
root_->Add(tabHolder_);
+3 -1
View File
@@ -20,6 +20,7 @@ enum class TabDialogFlags {
HorizontalOnlyIcons = 1,
VerticalShowIcons = 2,
AddTitles = 4,
ContextMenuInPortrait = 8,
};
ENUM_CLASS_BITOPS(TabDialogFlags);
@@ -45,9 +46,10 @@ protected:
// Load data and define your tabs here.
virtual void PreCreateViews() {}
virtual void CreateTabs() = 0;
virtual void CreateExtraButtons(UI::LinearLayout *verticalLayout, int margins) {}
virtual void CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) {}
virtual bool ShowSearchControls() const { return true; }
virtual void EnsureTabs();
virtual bool UsePopupMenuInPortrait() const { return false; }
virtual bool ForceHorizontalTabs() const { return false; }
int GetCurrentTab() const;
+1 -1
View File
@@ -155,7 +155,7 @@ void RightAnalogMappingScreen::CreateViews() {
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
Choice *back = new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK"), 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, TabHolderFlags::Default, nullptr, new AnchorLayoutParams(10, 0, 10, 0, Centering::None));
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, leftColumnWidth, TabHolderFlags::Default, nullptr, nullptr, new AnchorLayoutParams(10, 0, 10, 0, Centering::None));
root_->Add(tabHolder);
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
tabHolder->AddTab(co->T("Binds"), ImageID::invalid(), rightPanel);