From ce0b130d6ceb2145c8150eecbffe7380948899d4 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 13 Apr 2019 11:00:35 +0000 Subject: [PATCH] Disable mnemonics when pathnames are used as menu item labels. Based on a patch by Matthew White. --- src/graphicswin.cpp | 4 ++-- src/platform/gui.h | 3 ++- src/platform/guigtk.cpp | 7 ++++--- src/platform/guimac.mm | 5 +++-- src/platform/guiwin.cpp | 15 +++++++++++++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index 50a51d9d..8cd96f59 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -344,8 +344,8 @@ static void PopulateMenuWithPathnames(Platform::MenuRef menu, menuItem->SetEnabled(false); } else { for(Platform::Path pathname : pathnames) { - Platform::MenuItemRef menuItem = menu->AddItem(pathname.raw); - menuItem->onTrigger = [=]() { onTrigger(pathname); }; + Platform::MenuItemRef menuItem = menu->AddItem(pathname.raw, + [=]() { onTrigger(pathname); }, /*mnemonics=*/false); } } } diff --git a/src/platform/gui.h b/src/platform/gui.h index 74e7ee3b..3dd927f9 100644 --- a/src/platform/gui.h +++ b/src/platform/gui.h @@ -171,7 +171,8 @@ public: virtual ~Menu() {} virtual std::shared_ptr AddItem( - const std::string &label, std::function onTrigger = std::function()) = 0; + const std::string &label, std::function onTrigger = std::function(), + bool mnemonics = true) = 0; virtual std::shared_ptr AddSubMenu(const std::string &label) = 0; virtual void AddSeparator() = 0; diff --git a/src/platform/guigtk.cpp b/src/platform/guigtk.cpp index b1ca3878..8f57afd7 100644 --- a/src/platform/guigtk.cpp +++ b/src/platform/guigtk.cpp @@ -345,12 +345,13 @@ public: std::vector> subMenus; MenuItemRef AddItem(const std::string &label, - std::function onTrigger = NULL) override { + std::function onTrigger = NULL, + bool mnemonics = true) override { auto menuItem = std::make_shared(); menuItems.push_back(menuItem); - menuItem->gtkMenuItem.set_label(PrepareMnemonics(label)); - menuItem->gtkMenuItem.set_use_underline(true); + menuItem->gtkMenuItem.set_label(mnemonics ? PrepareMnemonics(label) : label); + menuItem->gtkMenuItem.set_use_underline(mnemonics); menuItem->gtkMenuItem.show(); menuItem->onTrigger = onTrigger; gtkMenu.append(menuItem->gtkMenuItem); diff --git a/src/platform/guimac.mm b/src/platform/guimac.mm index d9bef7c2..96b8b439 100644 --- a/src/platform/guimac.mm +++ b/src/platform/guimac.mm @@ -257,12 +257,13 @@ public: } MenuItemRef AddItem(const std::string &label, - std::function onTrigger = NULL) override { + std::function onTrigger = NULL, + bool mnemonics = true) override { auto menuItem = std::make_shared(); menuItems.push_back(menuItem); menuItem->onTrigger = onTrigger; - [menuItem->nsMenuItem setTitle:Wrap(PrepareMnemonics(label))]; + [menuItem->nsMenuItem setTitle:Wrap(mnemonics ? PrepareMnemonics(label) : label)]; [nsMenu addItem:menuItem->nsMenuItem]; return menuItem; diff --git a/src/platform/guiwin.cpp b/src/platform/guiwin.cpp index 0da75a8c..2f5b3a3e 100644 --- a/src/platform/guiwin.cpp +++ b/src/platform/guiwin.cpp @@ -107,6 +107,15 @@ static std::wstring PrepareTitle(const std::string &s) { return Widen("SolveSpace - " + s); } +static std::string NegateMnemonics(const std::string &label) { + std::string newLabel; + for(char c : label) { + newLabel.push_back(c); + if(c == '&') newLabel.push_back(c); + } + return newLabel; +} + static int Clamp(int x, int a, int b) { return max(a, min(x, b)); } @@ -353,13 +362,15 @@ public: } MenuItemRef AddItem(const std::string &label, - std::function onTrigger = NULL) override { + std::function onTrigger = NULL, + bool mnemonics = true) override { auto menuItem = std::make_shared(); menuItem->menu = weakThis.lock(); menuItem->onTrigger = onTrigger; menuItems.push_back(menuItem); - sscheck(AppendMenuW(hMenu, MF_STRING, (UINT_PTR)menuItem.get(), Widen(label).c_str())); + sscheck(AppendMenuW(hMenu, MF_STRING, (UINT_PTR)menuItem.get(), + Widen(mnemonics ? label : NegateMnemonics(label)).c_str())); // uID is just an UINT, which isn't large enough to hold a pointer on 64-bit Windows, // so we use dwItemData, which is.