diff options
author | Maxim Nikolenko <maximnproductengine@lindenlab.com> | 2024-08-02 18:47:44 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-02 18:47:44 +0300 |
commit | d6abce3968925c5cb58c11f1c6fc936605f55c57 (patch) | |
tree | 16142170d61f2ecf0ad8a4d6194a152658527589 /indra/newview | |
parent | 2390b0d623a09c0ec4f46fa10567bb02b7d49cfe (diff) | |
parent | 365030aa33d991006e093557cb7ce93d18ea2e4e (diff) |
Merge pull request #2047 from secondlife/lua-top-menu
Lua api for adding new menu items to the Top menu
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/lluilistener.cpp | 162 | ||||
-rw-r--r-- | indra/newview/lluilistener.h | 13 | ||||
-rw-r--r-- | indra/newview/scripts/lua/require/UI.lua | 34 | ||||
-rw-r--r-- | indra/newview/scripts/lua/test_callables.lua | 6 | ||||
-rw-r--r-- | indra/newview/scripts/lua/test_top_menu.lua | 34 |
5 files changed, 244 insertions, 5 deletions
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp index 4afd7f1766..b81859a764 100644 --- a/indra/newview/lluilistener.cpp +++ b/indra/newview/lluilistener.cpp @@ -34,10 +34,13 @@ // std headers // external library headers // other Linden headers +#include "llmenugl.h" #include "llui.h" // getRootView(), resolvePath() #include "lluictrl.h" #include "llerror.h" +extern LLMenuBarGL* gMenuBarView; + #define THROTTLE_PERIOD 1.5 // required seconds between throttled functions #define MIN_THROTTLE 0.5 @@ -52,11 +55,48 @@ LLUIListener::LLUIListener(): &LLUIListener::call, llsd::map("function", LLSD(), "reply", LLSD())); + add("callables", + "Return a list [\"callables\"] of dicts {name, access} of functions registered to\n" + "invoke with \"call\".\n" + "access has values \"allow\", \"block\" or \"throttle\".", + &LLUIListener::callables, + llsd::map("reply", LLSD::String())); + add("getValue", "For the UI control identified by the path in [\"path\"], return the control's\n" "current value as [\"value\"] reply.", &LLUIListener::getValue, llsd::map("path", LLSD(), "reply", LLSD())); + + add("getParents", + "List names of Top menus suitable for passing as \"parent_menu\"", + &LLUIListener::getParents, + llsd::map("reply", LLSD::String())); + + LLSD required_args = llsd::map("name", LLSD(), "label", LLSD(), "reply", LLSD()); + add("addMenu", + "Add new drop-down menu [\"name\"] with displayed [\"label\"] to the Top menu.", + &LLUIListener::addMenu, + required_args); + + required_args.insert("parent_menu", LLSD()); + add("addMenuBranch", + "Add new menu branch [\"name\"] with displayed [\"label\"]\n" + "to the [\"parent_menu\"] within the Top menu.", + &LLUIListener::addMenuBranch, + required_args); + + add("addMenuItem", + "Add new menu item [\"name\"] with displayed [\"label\"]\n" + "and call-on-click UI function [\"func\"] with optional [\"param\"]\n" + "to the [\"parent_menu\"] within the Top menu.", + &LLUIListener::addMenuItem, + required_args.with("func", LLSD())); + + add("addMenuSeparator", + "Add menu separator to the [\"parent_menu\"] within the Top menu.", + &LLUIListener::addMenuSeparator, + llsd::map("parent_menu", LLSD(), "reply", LLSD())); } typedef LLUICtrl::CommitCallbackInfo cb_info; @@ -103,7 +143,43 @@ void LLUIListener::call(const LLSD& event) (info->callback_func)(NULL, event["parameter"]); } -void LLUIListener::getValue(const LLSD&event) const +void LLUIListener::callables(const LLSD& event) const +{ + Response response(LLSD(), event); + + using Registry = LLUICtrl::CommitCallbackRegistry; + using Method = Registry::Registrar& (*)(); + static Method registrars[] = + { + &Registry::defaultRegistrar, + &Registry::currentRegistrar, + }; + LLSD list; + for (auto method : registrars) + { + auto& registrar{ (*method)() }; + for (auto it = registrar.beginItems(), end = registrar.endItems(); it != end; ++it) + { + LLSD entry{ llsd::map("name", it->first) }; + switch (it->second.handle_untrusted) + { + case LLUICtrl::CommitCallbackInfo::UNTRUSTED_ALLOW: + entry["access"] = "allow"; + break; + case LLUICtrl::CommitCallbackInfo::UNTRUSTED_BLOCK: + entry["access"] = "block"; + break; + case LLUICtrl::CommitCallbackInfo::UNTRUSTED_THROTTLE: + entry["access"] = "throttle"; + break; + } + list.append(entry); + } + } + response["callables"] = list; +} + +void LLUIListener::getValue(const LLSD& event) const { Response response(LLSD(), event); @@ -120,3 +196,87 @@ void LLUIListener::getValue(const LLSD&event) const response.error(stringize("UI control ", std::quoted(event["path"].asString()), " was not found")); } } + +void LLUIListener::getParents(const LLSD& event) const +{ + Response response(LLSD(), event); + response["parents"] = llsd::toArray( + *gMenuBarView->getChildList(), + [](auto childp) {return childp->getName(); }); +} + +LLMenuGL::Params get_params(const LLSD&event) +{ + LLMenuGL::Params item_params; + item_params.name = event["name"]; + item_params.label = event["label"]; + item_params.can_tear_off = true; + return item_params; +} + +LLMenuGL* get_parent_menu(LLEventAPI::Response& response, const LLSD&event) +{ + LLMenuGL* parent_menu = gMenuBarView->findChildMenuByName(event["parent_menu"], true); + if(!parent_menu) + { + response.error(stringize("Parent menu ", std::quoted(event["parent_menu"].asString()), " was not found")); + } + return parent_menu; +} + +void LLUIListener::addMenu(const LLSD&event) const +{ + Response response(LLSD(), event); + LLMenuGL::Params item_params = get_params(event); + if(!gMenuBarView->appendMenu(LLUICtrlFactory::create<LLMenuGL>(item_params))) + { + response.error(stringize("Menu ", std::quoted(event["name"].asString()), " was not added")); + } +} + +void LLUIListener::addMenuBranch(const LLSD&event) const +{ + Response response(LLSD(), event); + if(LLMenuGL* parent_menu = get_parent_menu(response, event)) + { + LLMenuGL::Params item_params = get_params(event); + if(!parent_menu->appendMenu(LLUICtrlFactory::create<LLMenuGL>(item_params))) + { + response.error(stringize("Menu branch ", std::quoted(event["name"].asString()), " was not added")); + } + } +} + +void LLUIListener::addMenuItem(const LLSD&event) const +{ + Response response(LLSD(), event); + LLMenuItemCallGL::Params item_params; + item_params.name = event["name"]; + item_params.label = event["label"]; + LLUICtrl::CommitCallbackParam item_func; + item_func.function_name = event["func"]; + if (event.has("param")) + { + item_func.parameter = event["param"]; + } + item_params.on_click = item_func; + if(LLMenuGL* parent_menu = get_parent_menu(response, event)) + { + if(!parent_menu->append(LLUICtrlFactory::create<LLMenuItemCallGL>(item_params))) + { + response.error(stringize("Menu item ", std::quoted(event["name"].asString()), " was not added")); + } + } +} + +void LLUIListener::addMenuSeparator(const LLSD&event) const +{ + Response response(LLSD(), event); + if(LLMenuGL* parent_menu = get_parent_menu(response, event)) + { + if(!parent_menu->addSeparator()) + { + response.error("Separator was not added"); + } + } +} diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h index 0df2afb3fe..671eb5f29b 100644 --- a/indra/newview/lluilistener.h +++ b/indra/newview/lluilistener.h @@ -39,12 +39,17 @@ class LLUIListener: public LLEventAPI public: LLUIListener(); -// FIXME These fields are intended to be private, changed here to support very hacky code in llluamanager.cpp -public: +private: void call(const LLSD& event); - void getValue(const LLSD&event) const; + void callables(const LLSD& event) const; + void getValue(const LLSD& event) const; + void getParents(const LLSD& event) const; + + void addMenu(const LLSD&event) const; + void addMenuBranch(const LLSD&event) const; + void addMenuItem(const LLSD&event) const; + void addMenuSeparator(const LLSD&event) const; - private: F64 mLastUntrustedThrottle {0}; F64 mLastMinThrottle {0}; }; diff --git a/indra/newview/scripts/lua/require/UI.lua b/indra/newview/scripts/lua/require/UI.lua index 1eee4657f4..06b49c6269 100644 --- a/indra/newview/scripts/lua/require/UI.lua +++ b/indra/newview/scripts/lua/require/UI.lua @@ -14,6 +14,10 @@ function UI.call(func, parameter) leap.request('UI', {op='call', ['function']=func, parameter=parameter}) end +function UI.callables() + return leap.request('UI', {op='callables'}).callables +end + function UI.getValue(path) return leap.request('UI', {op='getValue', path=path})['value'] end @@ -135,4 +139,34 @@ function UI.snapshot(...) args.op = 'saveSnapshot' return leap.request('LLViewerWindow', args).result end + +-- *************************************************************************** +-- Top menu +-- *************************************************************************** + +function UI.addMenu(...) + local args = mapargs('name,label', ...) + args.op = 'addMenu' + return leap.request('UI', args) +end + +function UI.addMenuBranch(...) + local args = mapargs('name,label,parent_menu', ...) + args.op = 'addMenuBranch' + return leap.request('UI', args) +end + +-- see UI.callables() for valid values of 'func' +function UI.addMenuItem(...) + local args = mapargs('name,label,parent_menu,func,param', ...) + args.op = 'addMenuItem' + return leap.request('UI', args) +end + +function UI.addMenuSeparator(...) + local args = mapargs('parent_menu', ...) + args.op = 'addMenuSeparator' + return leap.request('UI', args) +end + return UI diff --git a/indra/newview/scripts/lua/test_callables.lua b/indra/newview/scripts/lua/test_callables.lua new file mode 100644 index 0000000000..1bee062db8 --- /dev/null +++ b/indra/newview/scripts/lua/test_callables.lua @@ -0,0 +1,6 @@ +startup=require 'startup' +UI=require 'UI' +startup.wait('STATE_LOGIN_WAIT') +for _, cbl in pairs(UI.callables()) do + print(`{cbl.name} ({cbl.access})`) +end diff --git a/indra/newview/scripts/lua/test_top_menu.lua b/indra/newview/scripts/lua/test_top_menu.lua new file mode 100644 index 0000000000..780a384c92 --- /dev/null +++ b/indra/newview/scripts/lua/test_top_menu.lua @@ -0,0 +1,34 @@ +UI = require 'UI' + +--Add new drop-down 'LUA Menu' to the Top menu. +local MENU_NAME = "lua_menu" +UI.addMenu{name=MENU_NAME,label="LUA Menu"} + +--Add two new menu items to the 'LUA Menu': 'Debug console' and 'Scripts' +UI.addMenuItem{name="lua_debug",label="Debug console", + param="lua_debug", + func="Floater.ToggleOrBringToFront", + parent_menu=MENU_NAME} + +UI.addMenuItem{name="lua_scripts",label="Scripts", + param="lua_scripts", + func="Floater.ToggleOrBringToFront", + parent_menu=MENU_NAME} + +--Add menu separator to the 'LUA Menu' under added menu items +UI.addMenuSeparator{parent_menu=MENU_NAME} + +--Add two new menu branch 'About...' to the 'LUA Menu' +local BRANCH_NAME = "about_branch" +UI.addMenuBranch{name="about_branch",label="About...",parent_menu=MENU_NAME} + +--Add two new menu items to the 'About...' branch +UI.addMenuItem{name="lua_info",label="Lua...", + param="https://www.lua.org/about.html", + func="Advanced.ShowURL", + parent_menu=BRANCH_NAME} + +UI.addMenuItem{name="lua_info",label="Luau...", + param="https://luau-lang.org/", + func="Advanced.ShowURL", + parent_menu=BRANCH_NAME} |