Skip to content

Commit

Permalink
#5180: IMenuElements are now offering a clicked signal to subscribe to.
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed May 12, 2020
1 parent 3e04e41 commit 1c43062
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 9 deletions.
3 changes: 3 additions & 0 deletions include/iuimanager.h
Expand Up @@ -52,6 +52,9 @@ class IMenuElement
virtual bool isToggle() const = 0;

virtual void setToggled(bool isToggled) = 0;

// Callback triggered when this item is clicked
virtual sigc::signal<void>& signal_ItemActivated() = 0;
};

} // namespace ui
Expand Down
19 changes: 15 additions & 4 deletions radiant/eventmanager/EventManager.cpp
Expand Up @@ -314,7 +314,9 @@ void EventManager::setToggled(const std::string& name, const bool toggled)

void EventManager::registerMenuItem(const std::string& eventName, const ui::IMenuElementPtr& item)
{
_menuItems.emplace(eventName, item);
auto result = _menuItems.emplace(eventName, ItemConnection());

result->second.item = item;

// Set the accelerator of this menu item
auto& accelerator = findAccelerator(eventName);
Expand All @@ -328,15 +330,24 @@ void EventManager::registerMenuItem(const std::string& eventName, const ui::IMen
{
evt->connectMenuItem(item);
}
else
{
// There's no special event object this item is connected to
// just wire up an execute() when this item is clicked
result->second.itemActivatedConn = item->signal_ItemActivated().connect(
[=]() { GlobalCommandSystem().execute(eventName); }
);
}
}

void EventManager::unregisterMenuItem(const std::string& eventName, const ui::IMenuElementPtr& item)
{
for (auto it = _menuItems.lower_bound(eventName);
it != _menuItems.end() && it != _menuItems.upper_bound(eventName); ++it)
{
if (it->second == item)
if (it->second.item == item)
{
it->second.itemActivatedConn.disconnect();
_menuItems.erase(it);
break;
}
Expand Down Expand Up @@ -546,9 +557,9 @@ void EventManager::loadAcceleratorFromList(const xml::NodeList& shortcutList)
// Update all registered menu items
for (const auto& item : _menuItems)
{
if (item.second->getEvent() == cmd)
if (item.second.item->getEvent() == cmd)
{
item.second->setAccelerator(accelerator.getString(true));
item.second.item->setAccelerator(accelerator.getString(true));
}
}

Expand Down
9 changes: 8 additions & 1 deletion radiant/eventmanager/EventManager.h
Expand Up @@ -2,6 +2,7 @@

#include "ieventmanager.h"
#include <wx/event.h>
#include <sigc++/connection.h>

#include <map>
#include <list>
Expand All @@ -22,7 +23,13 @@ class EventManager :
// Each command has a name, this is the map where the name->command association is stored
typedef std::map<const std::string, IEventPtr> EventMap;

std::multimap<std::string, IMenuElementPtr> _menuItems;
struct ItemConnection
{
IMenuElementPtr item;
sigc::connection itemActivatedConn;
};

std::multimap<std::string, ItemConnection> _menuItems;

// The command-to-accelerator map containing all registered shortcuts
std::map<std::string, Accelerator::Ptr> _accelerators;
Expand Down
28 changes: 28 additions & 0 deletions radiant/eventmanager/Statement.cpp
Expand Up @@ -99,6 +99,34 @@ void Statement::onMenuItemClicked(wxCommandEvent& ev)
ev.Skip();
}

void Statement::connectMenuItem(const IMenuElementPtr& item)
{
if (_menuElements.find(item) != _menuElements.end())
{
rWarning() << "Cannot connect to the same menu item more than once." << std::endl;
return;
}

_menuElements.emplace(item,
item->signal_ItemActivated().connect(sigc::mem_fun(*this, &Statement::onItemActivated)));
}

void Statement::onItemActivated()
{
execute();
}

void Statement::disconnectMenuItem(const IMenuElementPtr& item)
{
if (_menuElements.find(item) == _menuElements.end())
{
rWarning() << "Cannot disconnect from unconnected menu item." << std::endl;
return;
}

_menuElements.erase(item);
}

void Statement::connectToolItem(wxToolBarToolBase* item)
{
if (_toolItems.find(item) != _toolItems.end())
Expand Down
7 changes: 7 additions & 0 deletions radiant/eventmanager/Statement.h
Expand Up @@ -35,6 +35,8 @@ class Statement :
typedef std::set<wxButton*> Buttons;
Buttons _buttons;

std::map<IMenuElementPtr, sigc::connection> _menuElements;

public:
Statement(const std::string& statement, bool reactOnKeyUp = false);

Expand All @@ -57,6 +59,9 @@ class Statement :
virtual void connectButton(wxButton* button);
virtual void disconnectButton(wxButton* button);

virtual void connectMenuItem(const IMenuElementPtr& item) override;
virtual void disconnectMenuItem(const IMenuElementPtr& item) override;

virtual bool empty() const;

virtual void connectAccelerator(IAccelerator& accel);
Expand All @@ -68,6 +73,8 @@ class Statement :
void onToolItemClicked(wxCommandEvent& ev);
void onButtonClicked(wxCommandEvent& ev);

void onItemActivated();

}; // class Statement

}
12 changes: 9 additions & 3 deletions radiant/eventmanager/Toggle.cpp
Expand Up @@ -63,9 +63,9 @@ void Toggle::updateWidgets()
(*i)->SetValue(_toggled);
}

for (const auto& item : _menuElements)
for (const auto& pair : _menuElements)
{
item->setToggled(_toggled);
pair.first->setToggled(_toggled);
}

_callbackActive = false;
Expand Down Expand Up @@ -94,11 +94,17 @@ void Toggle::connectMenuItem(const IMenuElementPtr& item)
return;
}

_menuElements.insert(item);
_menuElements.emplace(item,
item->signal_ItemActivated().connect(sigc::mem_fun(*this, &Toggle::onItemActivated)));

item->setToggled(_toggled);
}

void Toggle::onItemActivated()
{
toggle();
}

void Toggle::disconnectMenuItem(const IMenuElementPtr& item)
{
if (!item->isToggle())
Expand Down
4 changes: 3 additions & 1 deletion radiant/eventmanager/Toggle.h
Expand Up @@ -35,7 +35,7 @@ class Toggle :
typedef std::set<wxMenuItem*> MenuItems;
MenuItems _menuItems;

std::set<IMenuElementPtr> _menuElements;
std::map<IMenuElementPtr, sigc::connection> _menuElements;

typedef std::set<wxToolBarToolBase*> ToolItems;
ToolItems _toolItems;
Expand Down Expand Up @@ -95,6 +95,8 @@ class Toggle :
virtual void onToolItemClicked(wxCommandEvent& ev);
virtual void onToggleButtonClicked(wxCommandEvent& ev);

void onItemActivated();

}; // class Toggle
typedef std::shared_ptr<Toggle> TogglePtr;

Expand Down
7 changes: 7 additions & 0 deletions radiant/uimanager/menu/MenuElement.h
Expand Up @@ -52,6 +52,8 @@ class MenuElement :

static int _nextMenuItemId;

sigc::signal<void> _signalItemActivated;

public:
// Constructor, needs a name and a parent specified
MenuElement(const MenuElementPtr& parent = MenuElementPtr());
Expand Down Expand Up @@ -120,6 +122,11 @@ class MenuElement :
virtual void setToggled(bool isToggled) override
{}

virtual sigc::signal<void>& signal_ItemActivated() override
{
return _signalItemActivated;
}

// Tries to (recursively) locate the MenuElement by looking up the path
MenuElementPtr find(const std::string& menuPath);

Expand Down
9 changes: 9 additions & 0 deletions radiant/uimanager/menu/MenuItem.cpp
Expand Up @@ -80,6 +80,9 @@ void MenuItem::construct()
int pos = parent->getMenuPosition(shared_from_this());
menu->Insert(pos, _menuItem);

// Wire up the click event
menu->Bind(wxEVT_MENU, &MenuItem::onMenuItemClicked, this, _menuItem->GetId());

#if 0
if (event)
{
Expand All @@ -99,6 +102,11 @@ void MenuItem::construct()
MenuElement::constructChildren();
}

void MenuItem::onMenuItemClicked(wxCommandEvent& ev)
{
signal_ItemActivated().emit();
}

void MenuItem::setAccelerator(const std::string& accelStr)
{
if (_menuItem == nullptr) return;
Expand Down Expand Up @@ -131,6 +139,7 @@ void MenuItem::deconstruct()

if (_menuItem->GetMenu() != nullptr)
{
_menuItem->GetMenu()->Unbind(wxEVT_MENU, &MenuItem::onMenuItemClicked, this, _menuItem->GetId());
_menuItem->GetMenu()->Remove(_menuItem);
}

Expand Down
3 changes: 3 additions & 0 deletions radiant/uimanager/menu/MenuItem.h
Expand Up @@ -31,6 +31,9 @@ class MenuItem :
protected:
virtual void construct() override;
virtual void deconstruct() override;

private:
void onMenuItemClicked(wxCommandEvent& ev);
};

}

0 comments on commit 1c43062

Please sign in to comment.