diff --git a/indra/llui/lfidbearer.cpp b/indra/llui/lfidbearer.cpp index cc7a3f988..b9c2154c4 100644 --- a/indra/llui/lfidbearer.cpp +++ b/indra/llui/lfidbearer.cpp @@ -20,10 +20,33 @@ #include "linden_common.h" #include "lfidbearer.h" #include "llmenugl.h" +#include "lluictrlfactory.h" + +const std::array LFIDBearer::sMenuStrings +{ + "menu_avs_list.xml" // 0 +, "menu_groups_list.xml" // 1 // Singu TODO +, "menu_objects_list.xml" // 2 // Singu TODO +}; +std::array LFIDBearer::sMenus {}; -std::vector LFIDBearer::sMenus = {}; LFIDBearer* LFIDBearer::sActive = nullptr; +void LFIDBearer::buildMenus() +{ + auto& factory = LLUICtrlFactory::instance(); + for (auto i = 0; i < COUNT; ++i) + sMenus[i] = factory.buildMenu(sMenuStrings[i], LLMenuGL::sMenuContainer); +} + +LLMenuGL* LFIDBearer::showMenu(LLView* self, const std::string& menu_name, S32 x, S32 y, std::function on_menu_built) +{ + auto menu = LLUICtrlFactory::instance().buildMenu(menu_name, LLMenuGL::sMenuContainer); + if (on_menu_built) on_menu_built(menu); + showMenu(self, menu, x, y); + return menu; +} + void LFIDBearer::showMenu(LLView* self, LLMenuGL* menu, S32 x, S32 y) { sActive = this; // Menu listeners rely on this diff --git a/indra/llui/lfidbearer.h b/indra/llui/lfidbearer.h index e56ba8560..1cff25565 100644 --- a/indra/llui/lfidbearer.h +++ b/indra/llui/lfidbearer.h @@ -49,10 +49,13 @@ struct LFIDBearer static S32 getActiveNumSelected() { return sActive->getNumSelected(); } static Type getActiveType() { return sActive->getSelectedType(); } + static void buildMenus(); + LLMenuGL* showMenu(LLView* self, const std::string& menu_name, S32 x, S32 y, std::function on_menu_built = nullptr); void showMenu(LLView* self, LLMenuGL* menu, S32 x, S32 y); - static void addCommonMenu(LLMenuGL* menu) { sMenus.push_back(menu); } protected: - static std::vector sMenus; // Menus that recur, such as general avatars or groups menus + // Menus that recur, such as general avatars or groups menus + static const std::array sMenuStrings; + static std::array sMenus; static LFIDBearer* sActive; }; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index f46775f6f..72c61f819 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -2036,6 +2036,11 @@ void LLScrollListCtrl::setFilter(const std::string& filter) adjustScrollbar(unfiltered_count); } +void LLScrollListCtrl::setContextMenu(const std::string& menu) +{ + setContextMenu(LLUICtrlFactory::instance().buildMenu(menu, LLMenuGL::sMenuContainer)); +} + BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) { @@ -2695,17 +2700,17 @@ void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node) if (node->hasAttribute("menu_num")) { - // Some scroll lists use common menus identified by number - // 0 is menu_avs_list.xml, 1 will be for groups, 2 could be for lists of objects + // Some UI uses common menus identified by number + // 0 is avatars, 1 will be for groups, others could be for lists of objects or locations or experiences S32 menu_num; node->getAttributeS32("menu_num", menu_num); - setContextMenu(menu_num); + mPopupMenu = sMenus[menu_num]; } else if (node->hasAttribute("menu_file")) { - std::string menu_file; - node->getAttributeString("menu_file", menu_file); - mPopupMenu = LLUICtrlFactory::getInstance()->buildMenu(menu_file, LLMenuGL::sMenuContainer); + std::string menu; + node->getAttributeString("menu_file", menu); + if (!menu.empty()) setContextMenu(menu); } } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index c09af350a..97917ad5e 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -254,9 +254,10 @@ public: bool filterItem(LLScrollListItem* item); void setFilter(const std::string& filter); - // support right-click context menus for avatar/group lists + // Context Menus void setContextMenu(LLMenuGL* menu) { mPopupMenu = menu; } - void setContextMenu(S32 index) { mPopupMenu = sMenus[index]; } + void setContextMenu(U8 index) { mPopupMenu = sMenus[index]; } + void setContextMenu(const std::string& menu); // Overridden from LLView /*virtual*/ void draw(); diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp index 1e6331e4a..be90f20f5 100644 --- a/indra/newview/llnamebox.cpp +++ b/indra/newview/llnamebox.cpp @@ -67,10 +67,9 @@ BOOL LLNameBox::handleRightMouseDown(S32 x, S32 y, MASK mask) auto handled = LLTextBox::handleRightMouseDown(x, y, mask); if (mAllowInteract && !handled) { - // Singu TODO: Generic menus for groups - if (!mIsGroup && mNameID.notNull()) + if (mNameID.notNull()) { - showMenu(this, sMenus[0], x, y); + showMenu(this, sMenus[getSelectedType()], x, y); handled = true; } } diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp index c2706c297..1d6aa59c2 100644 --- a/indra/newview/llnameeditor.cpp +++ b/indra/newview/llnameeditor.cpp @@ -76,15 +76,14 @@ BOOL LLNameEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) { bool simple_menu = mContextMenuHandle.get()->getName() == "rclickmenu"; std::string new_menu; - // Singu TODO: Generic menus for groups - bool needs_simple = mIsGroup || !mAllowInteract || mNameID.isNull(); // Need simple if no ID or blocking interaction + bool needs_simple = !mAllowInteract || mNameID.isNull(); // Need simple if no ID or blocking interaction if (!simple_menu && needs_simple) // Switch to simple menu { new_menu = "menu_texteditor.xml"; } - else if (!needs_simple && simple_menu) + else // TODO: This is lazy, but I cannot recall a name editor that switches between group and avatar, so logic is not needed yet. { - new_menu = "menu_nameeditor_avatar.xml"; + new_menu = mIsGroup ? "menu_nameeditor_group.xml" : "menu_nameeditor_avatar.xml"; } if (!new_menu.empty()) setContextMenu(LLUICtrlFactory::instance().buildMenu(new_menu, LLMenuGL::sMenuContainer)); sActive = this; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index e5891e8fb..288af7934 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -749,8 +749,7 @@ void init_menus() gMenuHolder->addChild(gLoginMenuBarView); // Singu Note: Initialize common ScrollListMenus here - LFIDBearer::addCommonMenu(LLUICtrlFactory::getInstance()->buildMenu("menu_avs_list.xml", gMenuHolder)); // 0 - //LFIDBearer::addCommonMenu(LLUICtrlFactory::getInstance()->buildMenu("menu_groups_list.xml")); // 1 // Singu TODO + LFIDBearer::buildMenus(); LLView* ins = gMenuBarView->getChildView("insert_world", true, false); ins->setVisible(false); @@ -9328,7 +9327,7 @@ class ListStartCall : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLAvatarActions::startCall(LFIDBearer::getActiveSelectedID()); + (LFIDBearer::getActiveType == LFIDBearer::GROUP ? LLGroupActions::startCall : LLAvatarActions::startCall)(LFIDBearer::getActiveSelectedID()); return true; } }; @@ -9346,7 +9345,9 @@ class ListStartIM : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLAvatarActions::startIM(LFIDBearer::getActiveSelectedID()); + const auto&& im = LFIDBearer::getActiveType() == LFIDBearer::GROUP ? [](const LLUUID& id) { LLGroupActions::startIM(id); } : LLAvatarActions::startIM; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + im(id); return true; } }; @@ -9542,6 +9543,62 @@ struct MenuSLURLDict : public LLSingleton } }; +class ListIsInGroup : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + auto in_group = false; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (!(in_group = LLGroupActions::isInGroup(id))) + break; + gMenuHolder->findControl(userdata["control"].asString())->setValue(in_group); + return true; + } +}; + +class ListNotInGroup : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + auto in_group = true; + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + if (in_group = LLGroupActions::isInGroup(id)) + break; + gMenuHolder->findControl(userdata["control"].asString())->setValue(!in_group); + return true; + } +}; + +class ListLeave : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + LLGroupActions::leave(id); + return true; + } +}; + +class ListJoin : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + LLGroupActions::join(id); + return true; + } +}; + +class ListActivate : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + for (const auto& id : LFIDBearer::getActiveSelectedIDs()) + LLGroupActions::activate(id); + return true; + } +}; + class MediaCtrlCopyURL : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -9925,6 +9982,11 @@ void initialize_menus() addMenu(new ListEstateBan(), "List.EstateBan"); addMenu(new ListEstateEject(), "List.EstateEject"); addMenu(new ListToggleMute(), "List.ToggleMute"); + addMenu(new ListIsInGroup, "List.IsInGroup"); + addMenu(new ListNotInGroup, "List.NotInGroup"); + addMenu(new ListLeave, "List.Leave"); + addMenu(new ListJoin, "List.Join"); + addMenu(new ListActivate, "List.Activate"); add_radar_listeners(); diff --git a/indra/newview/skins/default/xui/en-us/menu_groups_list.xml b/indra/newview/skins/default/xui/en-us/menu_groups_list.xml new file mode 100644 index 000000000..0a8713753 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_groups_list.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/menu_nameeditor_group.xml b/indra/newview/skins/default/xui/en-us/menu_nameeditor_group.xml new file mode 100644 index 000000000..cd237eee9 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/menu_nameeditor_group.xml @@ -0,0 +1,3 @@ + + +