diff options
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
  | 
