diff options
| author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
|---|---|---|
| committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
| commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
| tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llgrouplist.cpp | |
| parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
| parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (diff) | |
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts:
# autobuild.xml
# indra/cmake/CMakeLists.txt
# indra/cmake/GoogleMock.cmake
# indra/llaudio/llaudioengine_fmodstudio.cpp
# indra/llaudio/llaudioengine_fmodstudio.h
# indra/llaudio/lllistener_fmodstudio.cpp
# indra/llaudio/lllistener_fmodstudio.h
# indra/llaudio/llstreamingaudio_fmodstudio.cpp
# indra/llaudio/llstreamingaudio_fmodstudio.h
# indra/llcharacter/llmultigesture.cpp
# indra/llcharacter/llmultigesture.h
# indra/llimage/llimage.cpp
# indra/llimage/llimagepng.cpp
# indra/llimage/llimageworker.cpp
# indra/llimage/tests/llimageworker_test.cpp
# indra/llmessage/tests/llmockhttpclient.h
# indra/llprimitive/llgltfmaterial.h
# indra/llrender/llfontfreetype.cpp
# indra/llui/llcombobox.cpp
# indra/llui/llfolderview.cpp
# indra/llui/llfolderviewmodel.h
# indra/llui/lllineeditor.cpp
# indra/llui/lllineeditor.h
# indra/llui/lltextbase.cpp
# indra/llui/lltextbase.h
# indra/llui/lltexteditor.cpp
# indra/llui/lltextvalidate.cpp
# indra/llui/lltextvalidate.h
# indra/llui/lluictrl.h
# indra/llui/llview.cpp
# indra/llwindow/llwindowmacosx.cpp
# indra/newview/app_settings/settings.xml
# indra/newview/llappearancemgr.cpp
# indra/newview/llappearancemgr.h
# indra/newview/llavatarpropertiesprocessor.cpp
# indra/newview/llavatarpropertiesprocessor.h
# indra/newview/llbreadcrumbview.cpp
# indra/newview/llbreadcrumbview.h
# indra/newview/llbreastmotion.cpp
# indra/newview/llbreastmotion.h
# indra/newview/llconversationmodel.h
# indra/newview/lldensityctrl.cpp
# indra/newview/lldensityctrl.h
# indra/newview/llface.inl
# indra/newview/llfloatereditsky.cpp
# indra/newview/llfloatereditwater.cpp
# indra/newview/llfloateremojipicker.h
# indra/newview/llfloaterimsessiontab.cpp
# indra/newview/llfloaterprofiletexture.cpp
# indra/newview/llfloaterprofiletexture.h
# indra/newview/llgesturemgr.cpp
# indra/newview/llgesturemgr.h
# indra/newview/llimpanel.cpp
# indra/newview/llimpanel.h
# indra/newview/llinventorybridge.cpp
# indra/newview/llinventorybridge.h
# indra/newview/llinventoryclipboard.cpp
# indra/newview/llinventoryclipboard.h
# indra/newview/llinventoryfunctions.cpp
# indra/newview/llinventoryfunctions.h
# indra/newview/llinventorygallery.cpp
# indra/newview/lllistbrowser.cpp
# indra/newview/lllistbrowser.h
# indra/newview/llpanelobjectinventory.cpp
# indra/newview/llpanelprofile.cpp
# indra/newview/llpanelprofile.h
# indra/newview/llpreviewgesture.cpp
# indra/newview/llsavedsettingsglue.cpp
# indra/newview/llsavedsettingsglue.h
# indra/newview/lltooldraganddrop.cpp
# indra/newview/llurllineeditorctrl.cpp
# indra/newview/llvectorperfoptions.cpp
# indra/newview/llvectorperfoptions.h
# indra/newview/llviewerparceloverlay.cpp
# indra/newview/llviewertexlayer.cpp
# indra/newview/llviewertexturelist.cpp
# indra/newview/macmain.h
# indra/test/test.cpp
Diffstat (limited to 'indra/newview/llgrouplist.cpp')
| -rw-r--r-- | indra/newview/llgrouplist.cpp | 1229 |
1 files changed, 622 insertions, 607 deletions
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index f060cdf906..d092445604 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -1,607 +1,622 @@ -/** - * @file llgrouplist.cpp - * @brief List of the groups the agent belongs to. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llgrouplist.h" - -// libs -#include "llbutton.h" -#include "llgroupiconctrl.h" -#include "llmenugl.h" -#include "lltextbox.h" -#include "lltextutil.h" -#include "lltrans.h" - -// newview -#include "llagent.h" -#include "llgroupactions.h" -#include "llfloaterreg.h" -#include "llviewercontrol.h" // for gSavedSettings -#include "llviewermenu.h" // for gMenuHolder -#include "llvoiceclient.h" - -static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); - -class LLGroupComparator : public LLFlatListView::ItemComparator -{ -public: - LLGroupComparator() {}; - - /** Returns true if item1 < item2, false otherwise */ - /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const - { - std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName(); - std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName(); - - LLStringUtil::toUpper(name1); - LLStringUtil::toUpper(name2); - - return name1 < name2; - } -}; - -class LLSharedGroupComparator : public LLFlatListView::ItemComparator -{ -public: - LLSharedGroupComparator() {}; - - /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const - { - const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1); - std::string name1 = group_item1->getGroupName(); - bool item1_shared = gAgent.isInGroup(group_item1->getGroupID(), true); - - const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2); - std::string name2 = group_item2->getGroupName(); - bool item2_shared = gAgent.isInGroup(group_item2->getGroupID(), true); - - if (item2_shared != item1_shared) - { - return item1_shared; - } - - LLStringUtil::toUpper(name1); - LLStringUtil::toUpper(name2); - - return name1 < name2; - } -}; - -static LLGroupComparator GROUP_COMPARATOR; -static LLSharedGroupComparator SHARED_GROUP_COMPARATOR; - -LLGroupList::Params::Params() -: for_agent("for_agent", true) -{ -} - -LLGroupList::LLGroupList(const Params& p) -: LLFlatListViewEx(p) - , mForAgent(p.for_agent) - , mDirty(true) // to force initial update - , mShowIcons(false) - , mShowNone(true) -{ - setCommitOnSelectionChange(true); - - // Set default sort order. - if (mForAgent) - { - setComparator(&GROUP_COMPARATOR); - } - else - { - // shared groups first - setComparator(&SHARED_GROUP_COMPARATOR); - } - - if (mForAgent) - { - enableForAgent(true); - } -} - -LLGroupList::~LLGroupList() -{ - if (mForAgent) gAgent.removeListener(this); - if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); -} - -void LLGroupList::enableForAgent(bool show_icons) -{ - mForAgent = true; - - mShowIcons = mForAgent && gSavedSettings.getBOOL("GroupListShowIcons") && show_icons; - - // Listen for agent group changes. - gAgent.addListener(this, "new group"); - - // Set up context menu. - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - - registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2)); - enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2)); - - LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml", - gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(context_menu) - mContextMenuHandle = context_menu->getHandle(); -} - -// virtual -void LLGroupList::draw() -{ - if (mDirty) - refresh(); - - LLFlatListView::draw(); -} - -// virtual -bool LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - bool handled = LLUICtrl::handleRightMouseDown(x, y, mask); - - if (mForAgent) - { - LLToggleableMenu* context_menu = mContextMenuHandle.get(); - if (context_menu && size() > 0) - { - context_menu->buildDrawLabels(); - context_menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, context_menu, x, y); - } - } - - return handled; -} - -// virtual -bool LLGroupList::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - bool handled = LLView::handleDoubleClick(x, y, mask); - // Handle double click only for the selected item in the list, skip clicks on empty space. - if (handled) - { - if (mDoubleClickSignal && getItemsRect().pointInRect(x, y)) - { - (*mDoubleClickSignal)(this, x, y, mask); - } - } - - return handled; -} - -void LLGroupList::setNameFilter(const std::string& filter) -{ - std::string filter_upper = filter; - LLStringUtil::toUpper(filter_upper); - if (mNameFilter != filter_upper) - { - mNameFilter = filter_upper; - - // set no items message depend on filter state - updateNoItemsMessage(filter); - - setDirty(); - } -} - -static bool findInsensitive(std::string haystack, const std::string& needle_upper) -{ - LLStringUtil::toUpper(haystack); - return haystack.find(needle_upper) != std::string::npos; -} - -void LLGroupList::refresh() -{ - if (mForAgent) - { - const LLUUID& highlight_id = gAgent.getGroupID(); - S32 count = gAgent.mGroups.size(); - LLUUID id; - bool have_filter = !mNameFilter.empty(); - - clear(); - - for(S32 i = 0; i < count; ++i) - { - id = gAgent.mGroups.at(i).mID; - const LLGroupData& group_data = gAgent.mGroups.at(i); - if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) - continue; - addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile); - } - - // Sort the list. - sort(); - - // Add "none" to list at top if filter not set (what's the point of filtering "none"?). - // but only if some real groups exists. EXT-4838 - if (!have_filter && count > 0 && mShowNone) - { - std::string loc_none = LLTrans::getString("GroupsNone"); - addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP); - } - - selectItemByUUID(highlight_id); - } - else - { - clear(); - - for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it) - { - addNewItem(it->second, it->first, LLUUID::null, ADD_BOTTOM); - } - - // Sort the list. - sort(); - } - - setDirty(false); - onCommit(); -} - -void LLGroupList::toggleIcons() -{ - // Save the new value for new items to use. - mShowIcons = !mShowIcons; - gSavedSettings.setBOOL("GroupListShowIcons", mShowIcons); - - // Show/hide icons for all existing items. - std::vector<LLPanel*> items; - getItems(items); - for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++) - { - static_cast<LLGroupListItem*>(*it)->setGroupIconVisible(mShowIcons); - } -} - -void LLGroupList::setGroups(const std::map< std::string,LLUUID> group_list) -{ - mGroups = group_list; - setDirty(true); -} - -////////////////////////////////////////////////////////////////////////// -// PRIVATE Section -////////////////////////////////////////////////////////////////////////// - -void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile) -{ - LLGroupListItem* item = new LLGroupListItem(mForAgent, mShowIcons); - - item->setGroupID(id); - item->setName(name, mNameFilter); - item->setGroupIconID(icon_id); - - item->getChildView("info_btn")->setVisible( false); - item->getChildView("profile_btn")->setVisible( false); - item->setGroupIconVisible(mShowIcons); - if (!mShowIcons) - { - item->setVisibleInProfile(visible_in_profile); - } - addItem(item, id, pos); - -// setCommentVisible(false); -} - -// virtual -bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) -{ - // Why is "new group" sufficient? - if (event->desc() == "new group") - { - setDirty(); - return true; - } - - if (event->desc() == "value_changed") - { - LLSD data = event->getValue(); - if (data.has("group_id") && data.has("visible")) - { - LLUUID group_id = data["group_id"].asUUID(); - bool visible = data["visible"].asBoolean(); - - std::vector<LLPanel*> items; - getItems(items); - for (std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) - { - LLGroupListItem* item = dynamic_cast<LLGroupListItem*>(*it); - if (item && item->getGroupID() == group_id) - { - item->setVisibleInProfile(visible); - break; - } - } - } - return true; - } - - return false; -} - -bool LLGroupList::onContextMenuItemClick(const LLSD& userdata) -{ - std::string action = userdata.asString(); - LLUUID selected_group = getSelectedUUID(); - - if (action == "view_info") - { - LLGroupActions::show(selected_group); - } - else if (action == "chat") - { - LLGroupActions::startIM(selected_group); - } - else if (action == "call") - { - LLGroupActions::startCall(selected_group); - } - else if (action == "activate") - { - LLGroupActions::activate(selected_group); - } - else if (action == "leave") - { - LLGroupActions::leave(selected_group); - } - - return true; -} - -bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata) -{ - LLUUID selected_group_id = getSelectedUUID(); - bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected - - // each group including "none" can be activated - if (userdata.asString() == "activate") - return gAgent.getGroupID() != selected_group_id; - - if (userdata.asString() == "call") - return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - - return real_group_selected; -} - -/************************************************************************/ -/* LLGroupListItem implementation */ -/************************************************************************/ - -LLGroupListItem::LLGroupListItem(bool for_agent, bool show_icons) -: LLPanel(), -mGroupIcon(NULL), -mGroupNameBox(NULL), -mInfoBtn(NULL), -mProfileBtn(NULL), -mVisibilityHideBtn(NULL), -mVisibilityShowBtn(NULL), -mGroupID(LLUUID::null), -mForAgent(for_agent) -{ - if (show_icons) - { - buildFromFile( "panel_group_list_item.xml"); - } - else - { - buildFromFile( "panel_group_list_item_short.xml"); - } -} - -LLGroupListItem::~LLGroupListItem() -{ - LLGroupMgr::getInstance()->removeObserver(this); -} - -//virtual -bool LLGroupListItem::postBuild() -{ - mGroupIcon = getChild<LLGroupIconCtrl>("group_icon"); - mGroupNameBox = getChild<LLTextBox>("group_name"); - - mInfoBtn = getChild<LLButton>("info_btn"); - mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this)); - - mProfileBtn = getChild<LLButton>("profile_btn"); - mProfileBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onProfileBtnClick(); }); - - mVisibilityHideBtn = findChild<LLButton>("visibility_hide_btn"); - if (mVisibilityHideBtn) - { - mVisibilityHideBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(false); }); - } - mVisibilityShowBtn = findChild<LLButton>("visibility_show_btn"); - if (mVisibilityShowBtn) - { - mVisibilityShowBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(true); }); - } - - // Remember group icon width including its padding from the name text box, - // so that we can hide and show the icon again later. - // Also note that panel_group_list_item and panel_group_list_item_short - // have icons of different sizes so we need to figure it per file. - mIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft; - - return true; -} - -//virtual -void LLGroupListItem::setValue( const LLSD& value ) -{ - if (!value.isMap()) return; - if (!value.has("selected")) return; - getChildView("selected_icon")->setVisible( value["selected"]); -} - -void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask) -{ - getChildView("hovered_icon")->setVisible( true); - if (mGroupID.notNull()) // don't show the info button for the "none" group - { - mInfoBtn->setVisible(true); - mProfileBtn->setVisible(true); - if (mForAgent && mVisibilityHideBtn) - { - LLGroupData agent_gdatap; - if (gAgent.getGroupData(mGroupID, agent_gdatap)) - { - mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile); - mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile); - } - } - } - - LLPanel::onMouseEnter(x, y, mask); -} - -void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask) -{ - getChildView("hovered_icon")->setVisible( false); - mInfoBtn->setVisible(false); - mProfileBtn->setVisible(false); - if (mVisibilityHideBtn) - { - mVisibilityHideBtn->setVisible(false); - mVisibilityShowBtn->setVisible(false); - } - - LLPanel::onMouseLeave(x, y, mask); -} - -void LLGroupListItem::setName(const std::string& name, const std::string& highlight) -{ - mGroupName = name; - LLTextUtil::textboxSetHighlightedVal(mGroupNameBox, mGroupNameStyle, name, highlight); - mGroupNameBox->setToolTip(name); -} - -void LLGroupListItem::setGroupID(const LLUUID& group_id) -{ - LLGroupMgr::getInstance()->removeObserver(this); - - mID = group_id; - mGroupID = group_id; - - if (mForAgent) - { - // Active group should be bold. - setBold(group_id == gAgent.getGroupID()); - } - else - { - // Groups shared with the agent should be bold - setBold(gAgent.isInGroup(group_id, true)); - } - - LLGroupMgr::getInstance()->addObserver(this); -} - -void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id) -{ - mGroupIcon->setIconId(group_icon_id); -} - -void LLGroupListItem::setGroupIconVisible(bool visible) -{ - // Already done? Then do nothing. - if (mGroupIcon->getVisible() == (bool)visible) - return; - - // Show/hide the group icon. - mGroupIcon->setVisible(visible); - - // Move the group name horizontally by icon size + its distance from the group name. - LLRect name_rect = mGroupNameBox->getRect(); - name_rect.mLeft += visible ? mIconWidth : -mIconWidth; - mGroupNameBox->setRect(name_rect); -} - -void LLGroupListItem::setVisibleInProfile(bool visible) -{ - mGroupNameBox->setColor(LLUIColorTable::instance().getColor((visible ? "GroupVisibleInProfile" : "GroupHiddenInProfile"), LLColor4::red).get()); -} - -////////////////////////////////////////////////////////////////////////// -// Private Section -////////////////////////////////////////////////////////////////////////// -void LLGroupListItem::setBold(bool bold) -{ - // *BUG: setName() overrides the style params. - - LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc()); - - // *NOTE dzaporozhan - // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font - // is predefined as bold (SansSerifSmallBold, for example) - new_desc.setStyle(bold ? LLFontGL::BOLD : LLFontGL::NORMAL); - LLFontGL* new_font = LLFontGL::getFont(new_desc); - mGroupNameStyle.font = new_font; - - // *NOTE: You cannot set the style on a text box anymore, you must - // rebuild the text. This will cause problems if the text contains - // hyperlinks, as their styles will be wrong. - mGroupNameBox->setText(mGroupName, mGroupNameStyle); -} - -void LLGroupListItem::onInfoBtnClick() -{ - LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", mGroupID)); -} - -void LLGroupListItem::onProfileBtnClick() -{ - LLGroupActions::show(mGroupID); -} - -void LLGroupListItem::onVisibilityBtnClick(bool new_visibility) -{ - LLGroupData agent_gdatap; - if (gAgent.getGroupData(mGroupID, agent_gdatap)) - { - gAgent.setUserGroupFlags(mGroupID, agent_gdatap.mAcceptNotices, new_visibility); - setVisibleInProfile(new_visibility); - mVisibilityHideBtn->setVisible(new_visibility); - mVisibilityShowBtn->setVisible(!new_visibility); - } -} - -void LLGroupListItem::changed(LLGroupChange gc) -{ - LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID); - if ((gc == GC_ALL || gc == GC_PROPERTIES) && group_data) - { - setGroupIconID(group_data->mInsigniaID); - } -} - -//EOF +/**
+ * @file llgrouplist.cpp
+ * @brief List of the groups the agent belongs to.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgrouplist.h"
+
+// libs
+#include "llbutton.h"
+#include "llgroupiconctrl.h"
+#include "llmenugl.h"
+#include "lltextbox.h"
+#include "lltextutil.h"
+#include "lltrans.h"
+
+// newview
+#include "llagent.h"
+#include "llgroupactions.h"
+#include "llfloaterreg.h"
+#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewermenu.h" // for gMenuHolder
+#include "llvoiceclient.h"
+
+static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
+
+class LLGroupComparator : public LLFlatListView::ItemComparator
+{
+public:
+ LLGroupComparator() {};
+
+ /** Returns true if item1 < item2, false otherwise */
+ /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
+ {
+ std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
+ std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+
+ return name1 < name2;
+ }
+};
+
+class LLSharedGroupComparator : public LLFlatListView::ItemComparator
+{
+public:
+ LLSharedGroupComparator() {};
+
+ /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
+ {
+ const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1);
+ std::string name1 = group_item1->getGroupName();
+ bool item1_shared = gAgent.isInGroup(group_item1->getGroupID(), true);
+
+ const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2);
+ std::string name2 = group_item2->getGroupName();
+ bool item2_shared = gAgent.isInGroup(group_item2->getGroupID(), true);
+
+ if (item2_shared != item1_shared)
+ {
+ return item1_shared;
+ }
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+
+ return name1 < name2;
+ }
+};
+
+static LLGroupComparator GROUP_COMPARATOR;
+static LLSharedGroupComparator SHARED_GROUP_COMPARATOR;
+
+LLGroupList::Params::Params()
+: for_agent("for_agent", true)
+{
+}
+
+LLGroupList::LLGroupList(const Params& p)
+: LLFlatListViewEx(p)
+ , mForAgent(p.for_agent)
+ , mDirty(true) // to force initial update
+ , mShowIcons(false)
+ , mShowNone(true)
+{
+ setCommitOnSelectionChange(true);
+
+ // Set default sort order.
+ if (mForAgent)
+ {
+ setComparator(&GROUP_COMPARATOR);
+ }
+ else
+ {
+ // shared groups first
+ setComparator(&SHARED_GROUP_COMPARATOR);
+ }
+
+ if (mForAgent)
+ {
+ enableForAgent(true);
+ }
+}
+
+LLGroupList::~LLGroupList()
+{
+ if (mForAgent) gAgent.removeListener(this);
+ if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
+}
+
+void LLGroupList::enableForAgent(bool show_icons)
+{
+ mForAgent = true;
+
+ mShowIcons = mForAgent && gSavedSettings.getBOOL("GroupListShowIcons") && show_icons;
+
+ // Listen for agent group changes.
+ gAgent.addListener(this, "new group");
+
+ // Set up context menu.
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2));
+ enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2));
+
+ LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml",
+ gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(context_menu)
+ mContextMenuHandle = context_menu->getHandle();
+}
+
+// virtual
+void LLGroupList::draw()
+{
+ if (mDirty)
+ refresh();
+
+ LLFlatListView::draw();
+}
+
+// virtual
+bool LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ bool handled = LLUICtrl::handleRightMouseDown(x, y, mask);
+
+ if (mForAgent)
+ {
+ LLToggleableMenu* context_menu = mContextMenuHandle.get();
+ if (context_menu && size() > 0)
+ {
+ context_menu->buildDrawLabels();
+ context_menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, context_menu, x, y);
+ }
+ }
+
+ return handled;
+}
+
+// virtual
+bool LLGroupList::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ bool handled = LLView::handleDoubleClick(x, y, mask);
+ // Handle double click only for the selected item in the list, skip clicks on empty space.
+ if (handled)
+ {
+ if (mDoubleClickSignal && getItemsRect().pointInRect(x, y))
+ {
+ (*mDoubleClickSignal)(this, x, y, mask);
+ }
+ }
+
+ return handled;
+}
+
+void LLGroupList::setNameFilter(const std::string& filter)
+{
+ std::string filter_upper = filter;
+ LLStringUtil::toUpper(filter_upper);
+ if (mNameFilter != filter_upper)
+ {
+ mNameFilter = filter_upper;
+
+ // set no items message depend on filter state
+ updateNoItemsMessage(filter);
+
+ setDirty();
+ }
+}
+
+static bool findInsensitive(std::string haystack, const std::string& needle_upper)
+{
+ LLStringUtil::toUpper(haystack);
+ return haystack.find(needle_upper) != std::string::npos;
+}
+
+void LLGroupList::refresh()
+{
+ if (mForAgent)
+ {
+ const LLUUID& highlight_id = gAgent.getGroupID();
+ S32 count = gAgent.mGroups.size();
+ LLUUID id;
+ bool have_filter = !mNameFilter.empty();
+
+ clear();
+
+ for(S32 i = 0; i < count; ++i)
+ {
+ id = gAgent.mGroups.at(i).mID;
+ const LLGroupData& group_data = gAgent.mGroups.at(i);
+ if (have_filter && !findInsensitive(group_data.mName, mNameFilter))
+ continue;
+ addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile);
+ }
+
+ // Sort the list.
+ sort();
+
+ // Add "none" to list at top if filter not set (what's the point of filtering "none"?).
+ // but only if some real groups exists. EXT-4838
+ if (!have_filter && count > 0 && mShowNone)
+ {
+ std::string loc_none = LLTrans::getString("GroupsNone");
+ addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
+ }
+
+ selectItemByUUID(highlight_id);
+ }
+ else
+ {
+ clear();
+
+ for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it)
+ {
+ addNewItem(it->second, it->first, LLUUID::null, ADD_BOTTOM);
+ }
+
+ // Sort the list.
+ sort();
+ }
+
+ setDirty(false);
+ onCommit();
+}
+
+void LLGroupList::toggleIcons()
+{
+ // Save the new value for new items to use.
+ mShowIcons = !mShowIcons;
+ gSavedSettings.setBOOL("GroupListShowIcons", mShowIcons);
+
+ // Show/hide icons for all existing items.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLGroupListItem*>(*it)->setGroupIconVisible(mShowIcons);
+ }
+}
+
+void LLGroupList::setGroups(const std::map< std::string,LLUUID> group_list)
+{
+ mGroups = group_list;
+ setDirty(true);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE Section
+//////////////////////////////////////////////////////////////////////////
+
+void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile)
+{
+ LLGroupListItem* item = new LLGroupListItem(mForAgent, mShowIcons);
+
+ item->setGroupID(id);
+ item->setName(name, mNameFilter);
+ item->setGroupIconID(icon_id);
+
+ item->getChildView("info_btn")->setVisible( false);
+ item->getChildView("profile_btn")->setVisible( false);
+ item->getChildView("notices_btn")->setVisible(false);
+ item->setGroupIconVisible(mShowIcons);
+ if (!mShowIcons)
+ {
+ item->setVisibleInProfile(visible_in_profile);
+ }
+ addItem(item, id, pos);
+
+// setCommentVisible(false);
+}
+
+// virtual
+bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ // Why is "new group" sufficient?
+ if (event->desc() == "new group")
+ {
+ setDirty();
+ return true;
+ }
+
+ if (event->desc() == "value_changed")
+ {
+ LLSD data = event->getValue();
+ if (data.has("group_id") && data.has("visible"))
+ {
+ LLUUID group_id = data["group_id"].asUUID();
+ bool visible = data["visible"].asBoolean();
+
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for (std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it)
+ {
+ LLGroupListItem* item = dynamic_cast<LLGroupListItem*>(*it);
+ if (item && item->getGroupID() == group_id)
+ {
+ item->setVisibleInProfile(visible);
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool LLGroupList::onContextMenuItemClick(const LLSD& userdata)
+{
+ std::string action = userdata.asString();
+ LLUUID selected_group = getSelectedUUID();
+
+ if (action == "view_info")
+ {
+ LLGroupActions::show(selected_group);
+ }
+ else if (action == "chat")
+ {
+ LLGroupActions::startIM(selected_group);
+ }
+ else if (action == "call")
+ {
+ LLGroupActions::startCall(selected_group);
+ }
+ else if (action == "activate")
+ {
+ LLGroupActions::activate(selected_group);
+ }
+ else if (action == "leave")
+ {
+ LLGroupActions::leave(selected_group);
+ }
+
+ return true;
+}
+
+bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
+{
+ LLUUID selected_group_id = getSelectedUUID();
+ bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected
+
+ // each group including "none" can be activated
+ if (userdata.asString() == "activate")
+ return gAgent.getGroupID() != selected_group_id;
+
+ if (userdata.asString() == "call")
+ return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
+
+ return real_group_selected;
+}
+
+/************************************************************************/
+/* LLGroupListItem implementation */
+/************************************************************************/
+
+LLGroupListItem::LLGroupListItem(bool for_agent, bool show_icons)
+: LLPanel(),
+mGroupIcon(NULL),
+mGroupNameBox(NULL),
+mInfoBtn(NULL),
+mProfileBtn(NULL),
+mNoticesBtn(NULL),
+mVisibilityHideBtn(NULL),
+mVisibilityShowBtn(NULL),
+mGroupID(LLUUID::null),
+mForAgent(for_agent)
+{
+ if (show_icons)
+ {
+ buildFromFile( "panel_group_list_item.xml");
+ }
+ else
+ {
+ buildFromFile( "panel_group_list_item_short.xml");
+ }
+}
+
+LLGroupListItem::~LLGroupListItem()
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+}
+
+//virtual
+bool LLGroupListItem::postBuild()
+{
+ mGroupIcon = getChild<LLGroupIconCtrl>("group_icon");
+ mGroupNameBox = getChild<LLTextBox>("group_name");
+
+ mInfoBtn = getChild<LLButton>("info_btn");
+ mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this));
+
+ mProfileBtn = getChild<LLButton>("profile_btn");
+ mProfileBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onProfileBtnClick(); });
+
+ mNoticesBtn = getChild<LLButton>("notices_btn");
+ mNoticesBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onNoticesBtnClick(); });
+
+ mVisibilityHideBtn = findChild<LLButton>("visibility_hide_btn");
+ if (mVisibilityHideBtn)
+ {
+ mVisibilityHideBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(false); });
+ }
+ mVisibilityShowBtn = findChild<LLButton>("visibility_show_btn");
+ if (mVisibilityShowBtn)
+ {
+ mVisibilityShowBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onVisibilityBtnClick(true); });
+ }
+
+ // Remember group icon width including its padding from the name text box,
+ // so that we can hide and show the icon again later.
+ // Also note that panel_group_list_item and panel_group_list_item_short
+ // have icons of different sizes so we need to figure it per file.
+ mIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft;
+
+ return true;
+}
+
+//virtual
+void LLGroupListItem::setValue( const LLSD& value )
+{
+ if (!value.isMap()) return;
+ if (!value.has("selected")) return;
+ getChildView("selected_icon")->setVisible( value["selected"]);
+}
+
+void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ getChildView("hovered_icon")->setVisible( true);
+ if (mGroupID.notNull()) // don't show the info button for the "none" group
+ {
+ mInfoBtn->setVisible(true);
+ mProfileBtn->setVisible(true);
+ if (mForAgent)
+ {
+ LLGroupData agent_gdatap;
+ if (gAgent.getGroupData(mGroupID, agent_gdatap))
+ {
+ if (mVisibilityHideBtn)
+ {
+ mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile);
+ mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile);
+ }
+ mNoticesBtn->setVisible(true);
+ }
+ }
+ }
+
+ LLPanel::onMouseEnter(x, y, mask);
+}
+
+void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ getChildView("hovered_icon")->setVisible( false);
+ mInfoBtn->setVisible(false);
+ mProfileBtn->setVisible(false);
+ mNoticesBtn->setVisible(false);
+ if (mVisibilityHideBtn)
+ {
+ mVisibilityHideBtn->setVisible(false);
+ mVisibilityShowBtn->setVisible(false);
+ }
+
+ LLPanel::onMouseLeave(x, y, mask);
+}
+
+void LLGroupListItem::setName(const std::string& name, const std::string& highlight)
+{
+ mGroupName = name;
+ LLTextUtil::textboxSetHighlightedVal(mGroupNameBox, mGroupNameStyle, name, highlight);
+ mGroupNameBox->setToolTip(name);
+}
+
+void LLGroupListItem::setGroupID(const LLUUID& group_id)
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+
+ mID = group_id;
+ mGroupID = group_id;
+
+ if (mForAgent)
+ {
+ // Active group should be bold.
+ setBold(group_id == gAgent.getGroupID());
+ }
+ else
+ {
+ // Groups shared with the agent should be bold
+ setBold(gAgent.isInGroup(group_id, true));
+ }
+
+ LLGroupMgr::getInstance()->addObserver(this);
+}
+
+void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id)
+{
+ mGroupIcon->setIconId(group_icon_id);
+}
+
+void LLGroupListItem::setGroupIconVisible(bool visible)
+{
+ // Already done? Then do nothing.
+ if (mGroupIcon->getVisible() == (bool)visible)
+ return;
+
+ // Show/hide the group icon.
+ mGroupIcon->setVisible(visible);
+
+ // Move the group name horizontally by icon size + its distance from the group name.
+ LLRect name_rect = mGroupNameBox->getRect();
+ name_rect.mLeft += visible ? mIconWidth : -mIconWidth;
+ mGroupNameBox->setRect(name_rect);
+}
+
+void LLGroupListItem::setVisibleInProfile(bool visible)
+{
+ mGroupNameBox->setColor(LLUIColorTable::instance().getColor((visible ? "GroupVisibleInProfile" : "GroupHiddenInProfile"), LLColor4::red).get());
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Private Section
+//////////////////////////////////////////////////////////////////////////
+void LLGroupListItem::setBold(bool bold)
+{
+ // *BUG: setName() overrides the style params.
+
+ LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc());
+
+ // *NOTE dzaporozhan
+ // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font
+ // is predefined as bold (SansSerifSmallBold, for example)
+ new_desc.setStyle(bold ? LLFontGL::BOLD : LLFontGL::NORMAL);
+ LLFontGL* new_font = LLFontGL::getFont(new_desc);
+ mGroupNameStyle.font = new_font;
+
+ // *NOTE: You cannot set the style on a text box anymore, you must
+ // rebuild the text. This will cause problems if the text contains
+ // hyperlinks, as their styles will be wrong.
+ mGroupNameBox->setText(mGroupName, mGroupNameStyle);
+}
+
+void LLGroupListItem::onInfoBtnClick()
+{
+ LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", mGroupID));
+}
+
+void LLGroupListItem::onProfileBtnClick()
+{
+ LLGroupActions::show(mGroupID);
+}
+
+void LLGroupListItem::onNoticesBtnClick()
+{
+ LLGroupActions::show(mGroupID, true);
+}
+
+void LLGroupListItem::onVisibilityBtnClick(bool new_visibility)
+{
+ LLGroupData agent_gdatap;
+ if (gAgent.getGroupData(mGroupID, agent_gdatap))
+ {
+ gAgent.setUserGroupFlags(mGroupID, agent_gdatap.mAcceptNotices, new_visibility);
+ setVisibleInProfile(new_visibility);
+ mVisibilityHideBtn->setVisible(new_visibility);
+ mVisibilityShowBtn->setVisible(!new_visibility);
+ }
+}
+
+void LLGroupListItem::changed(LLGroupChange gc)
+{
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID);
+ if ((gc == GC_ALL || gc == GC_PROPERTIES) && group_data)
+ {
+ setGroupIconID(group_data->mInsigniaID);
+ }
+}
+
+//EOF
|
