#pragma once #include #include #include #include namespace LooperUI { enum MenuType { MenuType_Default, MenuType_Item, MenuType_Separator, MenuType_Application, MenuType_Window, MenuType_Help, MenuType_Services, }; bool MenuTypeValidForSystem(MenuType type); class Menu; enum class OSOptions { AnyOS, OnlyMac, ExcludeMac }; class MenuItemBase { friend class Menu; Menu *parent; public: std::string id; MenuType type; OSOptions os_options; virtual bool IsSubmenu(); Menu *GetParent(); bool HasParent(); bool visible; bool enabled; std::string title; MenuItemBase(std::string title); MenuItemBase(MenuType type = MenuType_Separator); }; class MenuItem : public MenuItemBase { public: void *userdata; std::string keybindString; std::function callback; virtual void RunAction() { callback(this, userdata); } MenuItem(std::string title, std::string keybindString, std::function callback, void *userdata = nullptr); }; class Menu : public MenuItemBase { using container = std::vector; using iterator = container::iterator; using const_iterator = container::const_iterator; using reverse_iterator = container::reverse_iterator; using const_reverse_iterator = container::const_reverse_iterator; container children; friend class MenuIterator; public: bool IsSubmenu() override; void Append(MenuItemBase *menu); iterator begin(); iterator end(); const_iterator cbegin() const; const_iterator cend() const; reverse_iterator rbegin(); reverse_iterator rend(); const_reverse_iterator crbegin() const; const_reverse_iterator crend() const; MenuItemBase *operator [](size_t index); void Prepend(MenuItemBase *menu); void Insert(MenuItemBase *menu, size_t index); Menu(std::string title, MenuType type = MenuType_Default); }; class Menubar { }; class MenuBuilder { private: Menu *root; Menu *current_menu; bool built; void throwIfBuilt(); public: MenuBuilder &BeginSubmenu(std::string title, MenuType type = MenuType_Default, OSOptions allowedOS = OSOptions::AnyOS); MenuBuilder &EndSubmenu(); MenuBuilder &AddSeparator(OSOptions allowedOS = OSOptions::AnyOS); MenuBuilder &AddEmptySubmenu(std::string title, MenuType type = MenuType_Default, OSOptions allowedOS = OSOptions::AnyOS); MenuBuilder &AddItem(std::string title, std::string keybindString, std::function callback, void *userdata = nullptr, OSOptions allowedOS = OSOptions::AnyOS); MenuBuilder &AddItemNoUserdata(std::string title, std::string keybindString, std::function callback_no_userdata, OSOptions allowedOS = OSOptions::AnyOS); MenuBuilder &AddItemSimple(std::string title, std::string keybindString, std::function callback_simple, OSOptions allowedOS = OSOptions::AnyOS); Menu *Build(); MenuBuilder(std::string rootTitle = ""); }; // TODO: For DBusmenu struct PlatformData; struct MenuIteratorCallbacks { inline virtual void Init(Menu *root) { } inline virtual void Finalize() { } inline virtual void AddNormalItem(MenuItem* item) { } inline virtual void BeginSubmenu(Menu *menu) { } inline virtual void EndSubmenu() { } inline virtual void AddSeparator() { } }; MenuItemBase *FindMenu(Menu *menu, std::string title); void IterateMenu(Menu *menu, MenuIteratorCallbacks &callbacks); bool PublishMenu(Menu *menu, PlatformData *platform_data = nullptr); }