PageRenderTime 73ms CodeModel.GetById 40ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llgrouplist.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 425 lines | 278 code | 79 blank | 68 comment | 47 complexity | 20f0b354fd99eede3dd20f733217bbb1 MD5 | raw file
  1/** 
  2 * @file llgrouplist.cpp
  3 * @brief List of the groups the agent belongs to.
  4 *
  5 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llgrouplist.h"
 30
 31// libs
 32#include "llbutton.h"
 33#include "lliconctrl.h"
 34#include "llmenugl.h"
 35#include "lltextbox.h"
 36#include "lltextutil.h"
 37#include "lltrans.h"
 38
 39// newview
 40#include "llagent.h"
 41#include "llgroupactions.h"
 42#include "llfloaterreg.h"
 43#include "llviewercontrol.h"	// for gSavedSettings
 44#include "llviewermenu.h"		// for gMenuHolder
 45#include "llvoiceclient.h"
 46
 47static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
 48S32 LLGroupListItem::sIconWidth = 0;
 49
 50class LLGroupComparator : public LLFlatListView::ItemComparator
 51{
 52public:
 53	/** Returns true if item1 < item2, false otherwise */
 54	/*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
 55	{
 56		std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
 57		std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
 58
 59		LLStringUtil::toUpper(name1);
 60		LLStringUtil::toUpper(name2);
 61
 62		return name1 < name2;
 63	}
 64};
 65
 66static const LLGroupComparator GROUP_COMPARATOR;
 67
 68
 69LLGroupList::LLGroupList(const Params& p)
 70:	LLFlatListViewEx(p)
 71	, mDirty(true) // to force initial update
 72{
 73	// Listen for agent group changes.
 74	gAgent.addListener(this, "new group");
 75
 76	mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons");
 77	setCommitOnSelectionChange(true);
 78
 79	// Set default sort order.
 80	setComparator(&GROUP_COMPARATOR);
 81
 82	// Set up context menu.
 83	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 84	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
 85
 86	registrar.add("People.Groups.Action",			boost::bind(&LLGroupList::onContextMenuItemClick,	this, _2));
 87	enable_registrar.add("People.Groups.Enable",	boost::bind(&LLGroupList::onContextMenuItemEnable,	this, _2));
 88
 89	LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml",
 90			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 91	if(context_menu)
 92		mContextMenuHandle = context_menu->getHandle();
 93}
 94
 95LLGroupList::~LLGroupList()
 96{
 97	gAgent.removeListener(this);
 98	if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
 99}
100
101// virtual
102void LLGroupList::draw()
103{
104	if (mDirty)
105		refresh();
106
107	LLFlatListView::draw();
108}
109
110// virtual
111BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
112{
113	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
114
115	LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get();
116	if (context_menu && size() > 0)
117	{
118		context_menu->buildDrawLabels();
119		context_menu->updateParent(LLMenuGL::sMenuContainer);
120		LLMenuGL::showPopup(this, context_menu, x, y);
121	}
122
123	return handled;
124}
125
126void LLGroupList::setNameFilter(const std::string& filter)
127{
128	std::string filter_upper = filter;
129	LLStringUtil::toUpper(filter_upper);
130	if (mNameFilter != filter_upper)
131	{
132		mNameFilter = filter_upper;
133
134		// set no items message depend on filter state
135		updateNoItemsMessage(filter);
136
137		setDirty();
138	}
139}
140
141static bool findInsensitive(std::string haystack, const std::string& needle_upper)
142{
143    LLStringUtil::toUpper(haystack);
144    return haystack.find(needle_upper) != std::string::npos;
145}
146
147void LLGroupList::refresh()
148{
149	const LLUUID& 		highlight_id	= gAgent.getGroupID();
150	S32					count			= gAgent.mGroups.count();
151	LLUUID				id;
152	bool				have_filter		= !mNameFilter.empty();
153
154	clear();
155
156	for(S32 i = 0; i < count; ++i)
157	{
158		id = gAgent.mGroups.get(i).mID;
159		const LLGroupData& group_data = gAgent.mGroups.get(i);
160		if (have_filter && !findInsensitive(group_data.mName, mNameFilter))
161			continue;
162		addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM);
163	}
164
165	// Sort the list.
166	sort();
167
168	// Add "none" to list at top if filter not set (what's the point of filtering "none"?).
169	// but only if some real groups exists. EXT-4838
170	if (!have_filter && count > 0)
171	{
172		std::string loc_none = LLTrans::getString("GroupsNone");
173		addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
174	}
175
176	selectItemByUUID(highlight_id);
177
178	setDirty(false);
179	onCommit();
180}
181
182void LLGroupList::toggleIcons()
183{
184	// Save the new value for new items to use.
185	mShowIcons = !mShowIcons;
186	gSavedSettings.setBOOL("GroupListShowIcons", mShowIcons);
187
188	// Show/hide icons for all existing items.
189	std::vector<LLPanel*> items;
190	getItems(items);
191	for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
192	{
193		static_cast<LLGroupListItem*>(*it)->setGroupIconVisible(mShowIcons);
194	}
195}
196
197//////////////////////////////////////////////////////////////////////////
198// PRIVATE Section
199//////////////////////////////////////////////////////////////////////////
200
201void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos)
202{
203	LLGroupListItem* item = new LLGroupListItem();
204
205	item->setGroupID(id);
206	item->setName(name, mNameFilter);
207	item->setGroupIconID(icon_id);
208
209	item->getChildView("info_btn")->setVisible( false);
210	item->getChildView("profile_btn")->setVisible( false);
211	item->setGroupIconVisible(mShowIcons);
212
213	addItem(item, id, pos);
214
215//	setCommentVisible(false);
216}
217
218// virtual
219bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
220{
221	// Why is "new group" sufficient?
222	if (event->desc() == "new group")
223	{
224		setDirty();
225		return true;
226	}
227
228	return false;
229}
230
231bool LLGroupList::onContextMenuItemClick(const LLSD& userdata)
232{
233	std::string action = userdata.asString();
234	LLUUID selected_group = getSelectedUUID();
235
236	if (action == "view_info")
237	{
238		LLGroupActions::show(selected_group);
239	}
240	else if (action == "chat")
241	{
242		LLGroupActions::startIM(selected_group);
243	}
244	else if (action == "call")
245	{
246		LLGroupActions::startCall(selected_group);
247	}
248	else if (action == "activate")
249	{
250		LLGroupActions::activate(selected_group);
251	}
252	else if (action == "leave")
253	{
254		LLGroupActions::leave(selected_group);
255	}
256
257	return true;
258}
259
260bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
261{
262	LLUUID selected_group_id = getSelectedUUID();
263	bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected
264
265	// each group including "none" can be activated
266	if (userdata.asString() == "activate")
267		return gAgent.getGroupID() != selected_group_id;
268
269	if (userdata.asString() == "call")
270	  return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
271
272	return real_group_selected;
273}
274
275/************************************************************************/
276/*          LLGroupListItem implementation                              */
277/************************************************************************/
278
279LLGroupListItem::LLGroupListItem()
280:	LLPanel(),
281mGroupIcon(NULL),
282mGroupNameBox(NULL),
283mInfoBtn(NULL),
284mGroupID(LLUUID::null)
285{
286	buildFromFile( "panel_group_list_item.xml");
287
288	// Remember group icon width including its padding from the name text box,
289	// so that we can hide and show the icon again later.
290	if (!sIconWidth)
291	{
292		sIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft;
293	}
294}
295
296LLGroupListItem::~LLGroupListItem()
297{
298	LLGroupMgr::getInstance()->removeObserver(this);
299}
300
301//virtual
302BOOL  LLGroupListItem::postBuild()
303{
304	mGroupIcon = getChild<LLIconCtrl>("group_icon");
305	mGroupNameBox = getChild<LLTextBox>("group_name");
306
307	mInfoBtn = getChild<LLButton>("info_btn");
308	mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this));
309
310	childSetAction("profile_btn", boost::bind(&LLGroupListItem::onProfileBtnClick, this));
311
312	return TRUE;
313}
314
315//virtual
316void LLGroupListItem::setValue( const LLSD& value )
317{
318	if (!value.isMap()) return;
319	if (!value.has("selected")) return;
320	getChildView("selected_icon")->setVisible( value["selected"]);
321}
322
323void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask)
324{
325	getChildView("hovered_icon")->setVisible( true);
326	if (mGroupID.notNull()) // don't show the info button for the "none" group
327	{
328		mInfoBtn->setVisible(true);
329		getChildView("profile_btn")->setVisible( true);
330	}
331
332	LLPanel::onMouseEnter(x, y, mask);
333}
334
335void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask)
336{
337	getChildView("hovered_icon")->setVisible( false);
338	mInfoBtn->setVisible(false);
339	getChildView("profile_btn")->setVisible( false);
340
341	LLPanel::onMouseLeave(x, y, mask);
342}
343
344void LLGroupListItem::setName(const std::string& name, const std::string& highlight)
345{
346	mGroupName = name;
347	LLTextUtil::textboxSetHighlightedVal(mGroupNameBox, mGroupNameStyle, name, highlight);
348	mGroupNameBox->setToolTip(name);
349}
350
351void LLGroupListItem::setGroupID(const LLUUID& group_id)
352{
353	LLGroupMgr::getInstance()->removeObserver(this);
354	
355	mID = group_id;
356	mGroupID = group_id;
357	setActive(group_id == gAgent.getGroupID());
358
359	LLGroupMgr::getInstance()->addObserver(this);
360}
361
362void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id)
363{
364	if (group_icon_id.notNull())
365	{
366		mGroupIcon->setValue(group_icon_id);
367	}
368}
369
370void LLGroupListItem::setGroupIconVisible(bool visible)
371{
372	// Already done? Then do nothing.
373	if (mGroupIcon->getVisible() == (BOOL)visible)
374		return;
375
376	// Show/hide the group icon.
377	mGroupIcon->setVisible(visible);
378
379	// Move the group name horizontally by icon size + its distance from the group name.
380	LLRect name_rect = mGroupNameBox->getRect();
381	name_rect.mLeft += visible ? sIconWidth : -sIconWidth;
382	mGroupNameBox->setRect(name_rect);
383}
384
385//////////////////////////////////////////////////////////////////////////
386// Private Section
387//////////////////////////////////////////////////////////////////////////
388void LLGroupListItem::setActive(bool active)
389{
390	// *BUG: setName() overrides the style params.
391
392	// Active group should be bold.
393	LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->getFontDesc());
394
395	// *NOTE dzaporozhan
396	// On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font 
397	// is predefined as bold (SansSerifSmallBold, for example)
398	new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL);
399	LLFontGL* new_font = LLFontGL::getFont(new_desc);
400	mGroupNameStyle.font = new_font;
401
402	// *NOTE: You cannot set the style on a text box anymore, you must
403	// rebuild the text.  This will cause problems if the text contains
404	// hyperlinks, as their styles will be wrong.
405	mGroupNameBox->setText(mGroupName, mGroupNameStyle);
406}
407
408void LLGroupListItem::onInfoBtnClick()
409{
410	LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", mGroupID));
411}
412
413void LLGroupListItem::onProfileBtnClick()
414{
415	LLGroupActions::show(mGroupID);
416}
417
418void LLGroupListItem::changed(LLGroupChange gc)
419{
420	LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID);
421	if(group_data)
422		setGroupIconID(group_data->mInsigniaID);
423}
424
425//EOF