diff options
Diffstat (limited to 'wx+/context_menu.h')
-rw-r--r-- | wx+/context_menu.h | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/wx+/context_menu.h b/wx+/context_menu.h new file mode 100644 index 00000000..894da832 --- /dev/null +++ b/wx+/context_menu.h @@ -0,0 +1,81 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved * +// ************************************************************************** + +#ifndef CONTEXT_HEADER_18047302153418174632141234 +#define CONTEXT_HEADER_18047302153418174632141234 + +#include <vector> +#include <functional> +#include <wx/menu.h> +#include <wx/app.h> + +/* +A context menu supporting C++11 lambda callbacks! + +Usage: + ContextMenu menu; + menu.addItem(L"Some Label", [&]{ ...do something... }); -> capture by reference is fine, as long as captured variables have at least scope of ContextMenu::show()! + ... + menu.popup(wnd); +*/ + +namespace zen +{ +class ContextMenu : private wxEvtHandler +{ +public: + void addItem(const wxString& label, const std::function<void()>& command, const wxBitmap* bmp = NULL, bool enabled = true) + { + wxMenuItem* newItem = new wxMenuItem(&menu, wxID_ANY, label); + if (bmp) newItem->SetBitmap(*bmp); + if (!enabled) newItem->Enable(false); + menu.Append(newItem); //do NOT append item before setting bitmap! wxWidgets screws up for yet another crappy reason + menu.Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command), /*pass ownership*/ this); + } + + void addCheckBox(const wxString& label, const std::function<void()>& command, bool checked, bool enabled = true) + { + wxMenuItem* newItem = menu.AppendCheckItem(wxID_ANY, label); + newItem->Check(checked); + if (!enabled) newItem->Enable(false); + menu.Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command), /*pass ownership*/ this); + } + + void addRadio(const wxString& label, const std::function<void()>& command, bool checked, bool enabled = true) + { + wxMenuItem* newItem = menu.AppendRadioItem(wxID_ANY, label); + newItem->Check(checked); + if (!enabled) newItem->Enable(false); + menu.Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command), /*pass ownership*/ this); + } + + void addSeparator() { menu.AppendSeparator(); } + + void popup(wxWindow& wnd) //show popup menu + process lambdas + { + wnd.PopupMenu(&menu); + wxTheApp->ProcessPendingEvents(); //make sure lambdas are evaluated before going out of scope; + //although all events seem to be processed within wxWindows::PopupMenu, we shouldn't trust wxWidgets in this regard + } + +private: + void onSelection(wxCommandEvent& event) + { + if (auto cmd = dynamic_cast<GenericCommand*>(event.m_callbackUserData)) + (cmd->fun_)(); + } + + struct GenericCommand : public wxObject + { + GenericCommand(const std::function<void()>& fun) : fun_(fun) {} + std::function<void()> fun_; + }; + + wxMenu menu; +}; +} + +#endif //CONTEXT_HEADER_18047302153418174632141234 |