From 2c75946e6cfe2ca9e8dd2166940ce881be0b4e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Nov 2025 19:07:52 +0100 Subject: [PATCH] Switch ControlMappingScreen to a two-pane layout --- UI/ControlMappingScreen.cpp | 74 +++++++++++++++++---------------- UI/ControlMappingScreen.h | 11 ++--- UI/SimpleDialogScreen.cpp | 12 +++++- UI/TouchControlLayoutScreen.cpp | 2 +- 4 files changed, 55 insertions(+), 44 deletions(-) diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index db8af3610c..b887abeca1 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -107,7 +107,7 @@ void SingleControlMapper::Refresh() { float itemH = 55.0f; float leftColumnWidth = 200; - float rightColumnWidth = 350; // TODO: Should be flexible somehow. Maybe we need to implement Measure. + float rightColumnWidth = 350; LinearLayout *root = Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); root->SetSpacing(3.0f); @@ -233,61 +233,63 @@ static const BindingCategory cats[] = { {}, // sentinel }; -void ControlMappingScreen::CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) { + +void ControlMappingScreen::CreateSettingsViews(UI::ViewGroup *parent) { using namespace UI; auto km = GetI18NCategory(I18NCat::KEYMAPPING); - verticalLayout->Add(new Choice(km->T("Clear All")))->OnClick.Add([](UI::EventParams &) { + parent->Add(new Choice(km->T("Clear All")))->OnClick.Add([](UI::EventParams &) { KeyMap::ClearAllMappings(); }); - verticalLayout->Add(new Choice(km->T("Default All")))->OnClick.Add([](UI::EventParams &) { + parent->Add(new Choice(km->T("Default All")))->OnClick.Add([](UI::EventParams &) { KeyMap::RestoreDefault(); }); std::string sysName = System_GetProperty(SYSPROP_NAME); // If there's a builtin controller, restore to default should suffice. No need to conf the controller on top. if (!KeyMap::HasBuiltinController(sysName) && KeyMap::GetSeenPads().size()) { - verticalLayout->Add(new Choice(km->T("Autoconfigure")))->OnClick.Handle(this, &ControlMappingScreen::OnAutoConfigure); + parent->Add(new Choice(km->T("Autoconfigure")))->OnClick.Handle(this, &ControlMappingScreen::OnAutoConfigure); } - verticalLayout->Add(new CheckBox(&g_Config.bAllowMappingCombos, km->T("Allow combo mappings"))); - verticalLayout->Add(new CheckBox(&g_Config.bStrictComboOrder, km->T("Strict combo input order"))); - verticalLayout->Add(new Spacer(12.0f)); + parent->Add(new CheckBox(&g_Config.bAllowMappingCombos, km->T("Allow combo mappings"))); + parent->Add(new CheckBox(&g_Config.bStrictComboOrder, km->T("Strict combo input order"))); } -void ControlMappingScreen::CreateTabs() { +std::string_view ControlMappingScreen::GetTitle() const { + auto co = GetI18NCategory(I18NCat::CONTROLS); + return co->T("Control mapping"); +} + +void ControlMappingScreen::CreateContentViews(UI::ViewGroup *parent) { using namespace UI; + + LinearLayout *rootLayout = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); mappers_.clear(); + size_t numMappableKeys = 0; + const KeyMap::KeyMap_IntStrPair *mappableKeys = KeyMap::GetMappableKeys(&numMappableKeys); + auto km = GetI18NCategory(I18NCat::KEYMAPPING); - AddTab("keymap", "Control mapping", [this](UI::LinearLayout *parent) { - size_t numMappableKeys = 0; - const KeyMap::KeyMap_IntStrPair *mappableKeys = KeyMap::GetMappableKeys(&numMappableKeys); + bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; - bool portrait = this->GetDeviceOrientation() == DeviceOrientation::Portrait; - - auto km = GetI18NCategory(I18NCat::KEYMAPPING); - - int curCat = -1; - CollapsibleSection *curSection = nullptr; - for (size_t i = 0; i < numMappableKeys; i++) { - if (curCat < (int)ARRAY_SIZE(cats) && mappableKeys[i].key == cats[curCat + 1].firstKey) { - if (curCat >= 0) { - curSection->SetOpenPtr(&categoryToggles_[curCat]); - } - curCat++; - curSection = parent->Add(new CollapsibleSection(km->T(cats[curCat].catName))); - curSection->SetSpacing(6.0f); + int curCat = -1; + CollapsibleSection *curSection = nullptr; + for (size_t i = 0; i < numMappableKeys; i++) { + if (curCat < (int)ARRAY_SIZE(cats) && mappableKeys[i].key == cats[curCat + 1].firstKey) { + if (curCat >= 0) { + curSection->SetOpenPtr(&categoryToggles_[curCat]); } - SingleControlMapper *mapper = curSection->Add( - new SingleControlMapper(mappableKeys[i].key, mappableKeys[i].name, portrait, screenManager(), - new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - mapper->SetTag(StringFromFormat("KeyMap%s", mappableKeys[i].name)); - mappers_.push_back(mapper); + curCat++; + curSection = rootLayout->Add(new CollapsibleSection(km->T(cats[curCat].catName))); + curSection->SetSpacing(6.0f); } - if (curCat >= 0 && curSection) { - curSection->SetOpenPtr(&categoryToggles_[curCat]); - } - _dbg_assert_(curCat == ARRAY_SIZE(cats) - 2); // count the sentinel - }, TabFlags::Default); + SingleControlMapper *mapper = curSection->Add( + new SingleControlMapper(mappableKeys[i].key, mappableKeys[i].name, portrait, screenManager())); + mapper->SetTag(StringFromFormat("KeyMap%s", mappableKeys[i].name)); + mappers_.push_back(mapper); + } + if (curCat >= 0 && curSection) { + curSection->SetOpenPtr(&categoryToggles_[curCat]); + } + _dbg_assert_(curCat == ARRAY_SIZE(cats) - 2); // count the sentinel keyMapGeneration_ = KeyMap::g_controllerMapGeneration; } diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index 4741fac0dc..e65649fd20 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -37,9 +37,9 @@ class SingleControlMapper; -class ControlMappingScreen : public UITabbedBaseDialogScreen { +class ControlMappingScreen : public UITwoPaneBaseDialogScreen { public: - ControlMappingScreen(const Path &gamePath) : UITabbedBaseDialogScreen(gamePath, TabDialogFlags::ContextMenuInPortrait) { + ControlMappingScreen(const Path &gamePath) : UITwoPaneBaseDialogScreen(gamePath, TwoPaneFlags::SettingsInContextMenu | TwoPaneFlags::ContentsCanScroll) { categoryToggles_[0] = true; categoryToggles_[1] = true; categoryToggles_[2] = true; @@ -48,13 +48,14 @@ public: const char *tag() const override { return "ControlMapping"; } protected: - void CreateTabs() override; - void CreateExtraButtons(UI::ViewGroup *verticalLayout, int margins) override; + void CreateSettingsViews(UI::ViewGroup *parent) override; + void CreateContentViews(UI::ViewGroup *parent) override; void update() override; + std::string_view GetTitle() const override; + private: void OnAutoConfigure(UI::EventParams ¶ms); - bool ShowSearchControls() const override { return false; } void dialogFinished(const Screen *dialog, DialogResult result) override; diff --git a/UI/SimpleDialogScreen.cpp b/UI/SimpleDialogScreen.cpp index 452200f55f..4eec0d1a22 100644 --- a/UI/SimpleDialogScreen.cpp +++ b/UI/SimpleDialogScreen.cpp @@ -36,9 +36,17 @@ void UITwoPaneBaseDialogScreen::CreateViews() { BeforeCreateViews(); - auto createContentViews = [this](UI::ViewGroup *parent) { + auto createContentViews = [this, portrait](UI::ViewGroup *parent) { if (flags_ & TwoPaneFlags::ContentsCanScroll) { - ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f, Margins(8))); + Margins margins(8, 8, 8, 0); + if (flags_ & TwoPaneFlags::SettingsToTheRight) { + // If settings are in context menu, we want to avoid double margins on the sides. + margins.left = 0; + } else { + margins.right = 0; + } + + ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f, margins)); parent->Add(contentScroll); CreateContentViews(contentScroll); } else { diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index 26cb9f78bb..02058eeebf 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -676,7 +676,7 @@ void TouchControlLayoutScreen::CreateViews() { leftColumn->Add(new Spacer(0.0f)); LinearLayout* rightColumn = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f, Margins(0.0f, 12.0f, 12.0f, 12.0f)))); - rightColumn->Add(new TextView(co->T(DeviceOrientationToString(orientation)))); + rightColumn->Add(new TextView(co->T(DeviceOrientationToString(orientation))))->SetTextSize(TextSize::Small); rightColumn->Add(new Spacer(new LinearLayoutParams(1.0))); float previewHeight = bounds.h * layoutAreaScale; layoutView_ = rightColumn->Add(new ControlLayoutView(GetDeviceOrientation(), new LinearLayoutParams(FILL_PARENT, previewHeight)));