diff --git a/radiant/eventmanager/Accelerator.cpp b/radiant/eventmanager/Accelerator.cpp index 90d06ea3fd..4a04b450ee 100644 --- a/radiant/eventmanager/Accelerator.cpp +++ b/radiant/eventmanager/Accelerator.cpp @@ -9,15 +9,27 @@ namespace ui { +Accelerator::Accelerator() : + _key(0), + _modifiers(0), + _isEmpty(true) +{} + // Construct an accelerator out of the key/modifier plus a command Accelerator::Accelerator(const unsigned int key, const unsigned int modifiers, const IEventPtr& event) : - _key(key), - _modifiers(modifiers), - _event(event) + _key(key), + _modifiers(modifiers), + _event(event), + _isEmpty(false) {} +Accelerator Accelerator::CreateEmpty() +{ + return Accelerator(); +} + // Returns true if the key/modifier combination matches this accelerator bool Accelerator::match(const unsigned int key, const unsigned int modifiers) const { return (_key == key && _modifiers == modifiers); @@ -49,6 +61,7 @@ void Accelerator::setStatement(const std::string& statement) void Accelerator::setKey(const unsigned int key) { _key = key; + _isEmpty = _key != 0; } // Make the accelerator use the specified accelerators @@ -66,6 +79,11 @@ void Accelerator::setEvent(const IEventPtr& ev) _event = ev; } +bool Accelerator::isEmpty() const +{ + return _isEmpty; +} + std::string Accelerator::getString(bool forMenu) const { const std::string keyStr = _key != 0 ? Accelerator::getNameFromKeyCode(_key) : ""; diff --git a/radiant/eventmanager/Accelerator.h b/radiant/eventmanager/Accelerator.h index 5839d7ca24..108abdf511 100644 --- a/radiant/eventmanager/Accelerator.h +++ b/radiant/eventmanager/Accelerator.h @@ -17,6 +17,7 @@ namespace ui class Accelerator : public IAccelerator { +private: // The internally stored key/modifier combination unsigned int _key; unsigned int _modifiers; @@ -27,6 +28,11 @@ class Accelerator : // Alternative if event is null: the command to execute std::string _statement; + bool _isEmpty; + + // Private constructor creating an empty accelerator + Accelerator(); + public: typedef std::shared_ptr Ptr; @@ -59,6 +65,8 @@ class Accelerator : std::string getString(bool forMenu) const override; + bool isEmpty() const; + /** * Converts a string representation of a key to the corresponding * wxKeyCode, e.g. "A" => 65, "TAB" => wxKeyCode::WXK_TAB. @@ -78,6 +86,9 @@ class Accelerator : * to its uppercase pendant if possible. 'a' => 'A' */ static std::string getNameFromKeyCode(unsigned int keyCode); + + // Create an empty accelerator + static Accelerator CreateEmpty(); }; typedef std::list AcceleratorList; diff --git a/radiant/eventmanager/EventManager.cpp b/radiant/eventmanager/EventManager.cpp index bfd7f4c6ba..84ecf71337 100644 --- a/radiant/eventmanager/EventManager.cpp +++ b/radiant/eventmanager/EventManager.cpp @@ -93,7 +93,7 @@ void EventManager::shutdownModule() // Constructor EventManager::EventManager() : _emptyEvent(new Event()), - _emptyAccelerator(0, 0, _emptyEvent) + _emptyAccelerator(Accelerator::CreateEmpty()) {} Accelerator& EventManager::addAccelerator(const std::string& key, const std::string& modifierStr) @@ -176,10 +176,10 @@ IEventPtr EventManager::findEvent(const std::string& name) IEventPtr EventManager::findEvent(wxKeyEvent& ev) { // Retrieve the accelerators for this eventkey - AcceleratorList accelList = findAccelerator(ev); + Accelerator& accel = findAccelerator(ev); // Did we find any matching accelerators? If yes, take the first found accelerator - return !accelList.empty() ? (*accelList.begin())->getEvent() : _emptyEvent; + return accel.getEvent() ? accel.getEvent() : _emptyEvent; } std::string EventManager::getEventName(const IEventPtr& event) @@ -471,22 +471,37 @@ void EventManager::loadAcceleratorFromList(const xml::NodeList& shortcutList) // Check for a non-empty key string if (key.empty()) continue; + // Check for duplicate accelerator mappings + const auto& existingAccel = findAccelerator(key, modifierStr); + + if (existingAccel.getStatement() == cmd) + { + rWarning() << "Accelerator " << existingAccel.getString(false) << + " is already mapped to " << cmd << std::endl; + continue; + } + + // Create the accelerator object + Accelerator& accelerator = addAccelerator(key, modifierStr); + + // Update all registered menu items + for (const auto& item : _menuItems) + { + if (item.second->getEvent() == cmd) + { + item.second->setAccelerator(accelerator.getString(true)); + } + } + // Try to lookup the command IEventPtr event = findEvent(cmd); // Check for valid command definitions were found if (!event->empty()) { - if (!duplicateAccelerator(key, modifierStr, event)) - { - // Create the accelerator object - Accelerator& accelerator = addAccelerator(key, modifierStr); - - // Connect the newly created accelerator to the command - event->connectAccelerator(accelerator); - accelerator.setEvent(event); - } - + // Connect the newly created accelerator to the command + event->connectAccelerator(accelerator); + accelerator.setEvent(event); continue; } @@ -498,19 +513,7 @@ void EventManager::loadAcceleratorFromList(const xml::NodeList& shortcutList) if (signatureIsEmptyOrOptional(signature)) { - bool accelExists = !findAccelerator(key, modifierStr).empty(); - - if (accelExists) - { - rWarning() << "EventManager: Shortcut is already taken: " - << modifierStr << "+" << key << std::endl; - continue; - } - - Accelerator& accelerator = addAccelerator(key, modifierStr); - accelerator.setStatement(cmd); - continue; } } @@ -583,8 +586,7 @@ void EventManager::saveEventListToRegistry() foreachEvent(visitor); } -AcceleratorList EventManager::findAccelerator( - const std::string& key, const std::string& modifierStr) +Accelerator& EventManager::findAccelerator(const std::string& key, const std::string& modifierStr) { unsigned int keyVal = Accelerator::getKeyCodeFromName(key); unsigned int modifierFlags = wxutil::Modifier::GetStateFromModifierString(modifierStr); @@ -596,7 +598,8 @@ bool EventManager::duplicateAccelerator(const std::string& key, const std::string& modifiers, const IEventPtr& event) { - AcceleratorList accelList = findAccelerator(key, modifiers); +#if 0 + Accelerator& accelerator = findAccelerator(key, modifiers); for (const auto& accelerator : accelList) { @@ -606,29 +609,26 @@ bool EventManager::duplicateAccelerator(const std::string& key, return true; } } - +#endif return false; } -AcceleratorList EventManager::findAccelerator(unsigned int keyVal, - const unsigned int modifierFlags) +Accelerator& EventManager::findAccelerator(unsigned int keyVal, unsigned int modifierFlags) { - AcceleratorList returnList; - // Cycle through the accelerators and check for matches - for (const auto& accelerator : _accelerators) + for (auto& accelerator : _accelerators) { if (accelerator->match(keyVal, modifierFlags)) { // Add the pointer to the found accelerators - returnList.push_back(accelerator); + return *accelerator; } } - return returnList; + return _emptyAccelerator; } -AcceleratorList EventManager::findAccelerator(wxKeyEvent& ev) +Accelerator& EventManager::findAccelerator(wxKeyEvent& ev) { int keyval = ev.GetKeyCode(); // is always uppercase @@ -637,41 +637,37 @@ AcceleratorList EventManager::findAccelerator(wxKeyEvent& ev) bool EventManager::handleKeyEvent(wxKeyEvent& keyEvent) { - AcceleratorList accelList = findAccelerator(keyEvent); + Accelerator& accelerator = findAccelerator(keyEvent); - // Pass the execute() call to all found accelerators - for (const auto& accelerator : accelList) - { - const std::string& statement = accelerator->getStatement(); + const std::string& statement = accelerator.getStatement(); - if (!statement.empty()) + if (!statement.empty()) + { + if (keyEvent.GetEventType() == wxEVT_KEY_DOWN) { - if (keyEvent.GetEventType() == wxEVT_KEY_DOWN) - { - GlobalCommandSystem().execute(statement); - } - - continue; + GlobalCommandSystem().execute(statement); } - auto ev = accelerator->getEvent(); + return true; + } + + auto ev = accelerator.getEvent(); - if (ev) + if (ev) + { + if (keyEvent.GetEventType() == wxEVT_KEY_DOWN) { - if (keyEvent.GetEventType() == wxEVT_KEY_DOWN) - { - ev->keyDown(); - } - else - { - ev->keyUp(); - } + ev->keyDown(); + } + else + { + ev->keyUp(); } - // Found an accelerator with no event or statement + return true; } - return !accelList.empty(); // accelerators found => true + return false; } bool EventManager::isModifier(wxKeyEvent& ev) diff --git a/radiant/eventmanager/EventManager.h b/radiant/eventmanager/EventManager.h index d98a0c8e91..b2e06fdeca 100644 --- a/radiant/eventmanager/EventManager.h +++ b/radiant/eventmanager/EventManager.h @@ -91,7 +91,7 @@ class EventManager : void foreachEvent(IEventVisitor& eventVisitor) override; // Tries to locate an accelerator, that is connected to the given command - AcceleratorList findAccelerator(wxKeyEvent& ev); + Accelerator& findAccelerator(wxKeyEvent& ev); bool handleKeyEvent(wxKeyEvent& keyEvent); std::string getEventStr(wxKeyEvent& ev) override; @@ -101,12 +101,12 @@ class EventManager : Accelerator& findAccelerator(const IEventPtr& event); Accelerator& findAccelerator(const std::string& commandName); - AcceleratorList findAccelerator(const std::string& key, const std::string& modifierStr); + Accelerator& findAccelerator(const std::string& key, const std::string& modifierStr); bool duplicateAccelerator(const std::string& key, const std::string& modifiers, const IEventPtr& event); // Returns the pointer to the accelerator for the given event, but convert the key to uppercase before passing it - AcceleratorList findAccelerator(unsigned int keyVal, const unsigned int modifierFlags); + Accelerator& findAccelerator(unsigned int keyVal, const unsigned int modifierFlags); void loadAcceleratorFromList(const xml::NodeList& shortcutList); diff --git a/radiant/eventmanager/Statement.cpp b/radiant/eventmanager/Statement.cpp index 58f62eb30d..64eb8f5ef5 100644 --- a/radiant/eventmanager/Statement.cpp +++ b/radiant/eventmanager/Statement.cpp @@ -180,10 +180,12 @@ void Statement::onButtonClicked(wxCommandEvent& ev) void Statement::connectAccelerator(IAccelerator& accel) { +#if 0 for (wxMenuItem* item : _menuItems) { setMenuItemAccelerator(item, static_cast(accel)); } +#endif for (wxToolBarToolBase* tool : _toolItems) { @@ -193,10 +195,12 @@ void Statement::connectAccelerator(IAccelerator& accel) void Statement::disconnectAccelerators() { +#if 0 for (wxMenuItem* item : _menuItems) { clearMenuItemAccelerator(item); } +#endif for (wxToolBarToolBase* tool : _toolItems) { diff --git a/radiant/uimanager/menu/MenuItem.cpp b/radiant/uimanager/menu/MenuItem.cpp index dee8791a55..f20c27623e 100644 --- a/radiant/uimanager/menu/MenuItem.cpp +++ b/radiant/uimanager/menu/MenuItem.cpp @@ -50,9 +50,7 @@ void MenuItem::construct() std::string caption = _caption; -#if 1 - GlobalEventManager().registerMenuItem(_event, shared_from_this()); -#else +#if 0 // Try to lookup the event name IEventPtr event = GlobalEventManager().findEvent(_event); @@ -94,6 +92,10 @@ void MenuItem::construct() } #endif +#if 1 + GlobalEventManager().registerMenuItem(_event, shared_from_this()); +#endif + MenuElement::constructChildren(); }