diff options
Diffstat (limited to 'indra/newview/llnamelistctrl.cpp')
-rw-r--r-- | indra/newview/llnamelistctrl.cpp | 1244 |
1 files changed, 622 insertions, 622 deletions
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 78114d5842..d7ffcb6e25 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -1,622 +1,622 @@ -/**
- * @file llnamelistctrl.cpp
- * @brief A list of names, automatically refreshed from name cache.
- *
- * $LicenseInfo:firstyear=2003&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 "llnamelistctrl.h"
-
-#include <boost/tokenizer.hpp>
-
-#include "llavatarnamecache.h"
-#include "llcachename.h"
-#include "llfloater.h"
-#include "llfloaterreg.h"
-#include "llfloatersnapshot.h" // gSnapshotFloaterView
-#include "llinventory.h"
-#include "llscrolllistitem.h"
-#include "llscrolllistcell.h"
-#include "llscrolllistcolumn.h"
-#include "llsdparam.h"
-#include "lltooltip.h"
-#include "lltrans.h"
-
-static LLDefaultChildRegistry::Register<LLNameListCtrl> r("name_list");
-
-static constexpr S32 info_icon_size = 16;
-
-void LLNameListCtrl::NameTypeNames::declareValues()
-{
- declare("INDIVIDUAL", LLNameListCtrl::INDIVIDUAL);
- declare("GROUP", LLNameListCtrl::GROUP);
- declare("SPECIAL", LLNameListCtrl::SPECIAL);
-}
-
-LLNameListCtrl::Params::Params()
-: name_column(""),
- allow_calling_card_drop("allow_calling_card_drop", false),
- short_names("short_names", false)
-{
-}
-
-LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
-: LLScrollListCtrl(p),
- mNameColumnIndex(p.name_column.column_index),
- mNameColumn(p.name_column.column_name),
- mAllowCallingCardDrop(p.allow_calling_card_drop),
- mShortNames(p.short_names),
- mPendingLookupsRemaining(0),
- mHoverIconName("Info_Small"),
- mNameListType(INDIVIDUAL)
-{}
-
-// public
-LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos,
- bool enabled, const std::string& suffix, const std::string& prefix)
-{
- //LL_INFOS() << "LLNameListCtrl::addNameItem " << agent_id << LL_ENDL;
-
- NameItem item;
- item.value = agent_id;
- item.enabled = enabled;
- item.target = INDIVIDUAL;
-
- return addNameItemRow(item, pos, suffix, prefix);
-}
-
-// virtual, public
-bool LLNameListCtrl::handleDragAndDrop(
- S32 x, S32 y, MASK mask,
- bool drop,
- EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept,
- std::string& tooltip_msg)
-{
- if (!mAllowCallingCardDrop)
- {
- return false;
- }
-
- bool handled = false;
-
- if (cargo_type == DAD_CALLINGCARD)
- {
- if (drop)
- {
- LLInventoryItem* item = (LLInventoryItem *)cargo_data;
- addNameItem(item->getCreatorUUID());
- }
-
- *accept = ACCEPT_YES_MULTI;
- }
- else
- {
- *accept = ACCEPT_NO;
- if (tooltip_msg.empty())
- {
- if (!getToolTip().empty())
- {
- tooltip_msg = getToolTip();
- }
- else
- {
- // backwards compatable English tooltip (should be overridden in xml)
- tooltip_msg.assign("Drag a calling card here\nto add a resident.");
- }
- }
- }
-
- handled = true;
- LL_DEBUGS("UserInput") << "dragAndDrop handled by LLNameListCtrl " << getName() << LL_ENDL;
-
- return handled;
-}
-
-void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience)
-{
- if (isSpecialType())
- {
- mIconClickedSignal(avatar_id);
- return;
- }
- if(is_experience)
- {
- LLFloaterReg::showInstance("experience_profile", avatar_id, true);
- return;
- }
-
- if (is_group)
- LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id));
- else
- LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id));
-}
-
-void LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index )
-{
- S32 cur_index = getHighlightedItemInx();
- if (cur_index != target_index)
- {
- bool is_mouse_over_name_cell = false;
-
- S32 mouse_x, mouse_y;
- LLUI::getInstance()->getMousePositionLocal(this, &mouse_x, &mouse_y);
-
- S32 column_index = getColumnIndexFromOffset(mouse_x);
- LLScrollListItem* hit_item = hitItem(mouse_x, mouse_y);
- if (hit_item && column_index == mNameColumnIndex)
- {
- // Get the name cell which is currently under the mouse pointer.
- LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
- if (hit_cell)
- {
- is_mouse_over_name_cell = getCellRect(cur_index, column_index).pointInRect(mouse_x, mouse_y);
- }
- }
-
- // If the tool tip is visible and the mouse is over the currently highlighted item's name cell,
- // we should not reset the highlighted item index i.e. set mHighlightedItem = -1
- // and should not increase the width of the text inside the cell because it may
- // overlap the tool tip icon.
- if (LLToolTipMgr::getInstance()->toolTipVisible() && is_mouse_over_name_cell)
- return;
-
- if(0 <= cur_index && cur_index < (S32)getItemList().size())
- {
- LLScrollListItem* item = getItemList()[cur_index];
- if (item)
- {
- LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex));
- if (cell)
- cell->setTextWidth(cell->getTextWidth() + info_icon_size);
- }
- else
- {
- LL_WARNS() << "highlighted name list item is NULL" << LL_ENDL;
- }
- }
- if(target_index != -1)
- {
- LLScrollListItem* item = getItemList()[target_index];
- LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex));
- if (item)
- {
- if (cell)
- cell->setTextWidth(cell->getTextWidth() - info_icon_size);
- }
- else
- {
- LL_WARNS() << "target name item is NULL" << LL_ENDL;
- }
- }
- }
-
- LLScrollListCtrl::mouseOverHighlightNthItem(target_index);
-}
-
-//virtual
-bool LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
-{
- bool handled = false;
- S32 column_index = getColumnIndexFromOffset(x);
- LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y));
- LLFloater* floater = gFloaterView->getParentFloater(this);
-
-
- if (floater
- && floater->isFrontmost()
- && hit_item
- && ((column_index == mNameColumnIndex) || isSpecialType()))
- {
- // ...this is the column with the avatar name
- LLUUID item_id = isSpecialType() ? hit_item->getSpecialID() : hit_item->getUUID();
- if (item_id.notNull())
- {
- // ...valid avatar id
-
- LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
- if (hit_cell)
- {
- S32 row_index = getItemIndex(hit_item);
- LLRect cell_rect = getCellRect(row_index, isSpecialType() ? getNumColumns() - 1 : column_index);
- // Convert rect local to screen coordinates
- LLRect sticky_rect;
- localRectToScreen(cell_rect, &sticky_rect);
-
- // Spawn at right side of cell
- LLPointer<LLUIImage> icon = LLUI::getUIImage(mHoverIconName);
- S32 screenX = sticky_rect.mRight - info_icon_size;
- S32 screenY = sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight()) / 2;
- LLCoordGL pos(screenX, screenY);
-
- LLFloater* snapshot_floatr = gSnapshotFloaterView->getFrontmostClosableFloater();
- if (!snapshot_floatr || !snapshot_floatr->getRect().pointInRect(screenX + icon->getWidth(), screenY))
- {
- // Should we show a group or an avatar inspector?
- bool is_group = hit_item->isGroup();
- bool is_experience = hit_item->isExperience();
-
- LLToolTip::Params params;
- params.background_visible(false);
- params.click_callback(boost::bind(&LLNameListCtrl::showInspector, this, item_id, is_group, is_experience));
- params.delay_time(0.0f); // spawn instantly on hover
- params.image(icon);
- params.message("");
- params.padding(0);
- params.pos(pos);
- params.sticky_rect(sticky_rect);
-
- LLToolTipMgr::getInstance()->show(params);
- handled = true;
- }
- }
- }
- }
- if (!handled)
- {
- handled = LLScrollListCtrl::handleToolTip(x, y, mask);
- }
- return handled;
-}
-
-// virtual
-bool LLNameListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y));
- LLFloater* floater = gFloaterView->getParentFloater(this);
- if (floater && floater->isFrontmost() && hit_item)
- {
- if(hit_item->isGroup())
- {
- ContextMenuType prev_menu = getContextMenuType();
- setContextMenu(MENU_GROUP);
- bool handled = LLScrollListCtrl::handleRightMouseDown(x, y, mask);
- setContextMenu(prev_menu);
- return handled;
- }
- }
- return LLScrollListCtrl::handleRightMouseDown(x, y, mask);
-}
-
-// public
-void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos,
- bool enabled)
-{
- NameItem item;
- item.value = group_id;
- item.enabled = enabled;
- item.target = GROUP;
-
- addNameItemRow(item, pos);
-}
-
-// public
-void LLNameListCtrl::addGroupNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos)
-{
- item.target = GROUP;
- addNameItemRow(item, pos);
-}
-
-LLScrollListItem* LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos)
-{
- item.target = INDIVIDUAL;
- return addNameItemRow(item, pos);
-}
-
-LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
-{
- LLNameListCtrl::NameItem item_params;
- LLParamSDParser parser;
- parser.readSD(element, item_params);
- item_params.userdata = userdata;
- return addNameItemRow(item_params, pos);
-}
-
-
-LLScrollListItem* LLNameListCtrl::addNameItemRow(
- const LLNameListCtrl::NameItem& name_item,
- EAddPosition pos,
- const std::string& suffix,
- const std::string& prefix)
-{
- LLUUID id = name_item.value().asUUID();
- LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP, name_item.target() == EXPERIENCE);
-
- if (!item) return NULL;
-
- LLScrollListCtrl::addRow(item, name_item, pos);
-
- // use supplied name by default
- std::string fullname = name_item.name;
-
- switch(name_item.target)
- {
- case GROUP:
- if (!gCacheName->getGroupName(id, fullname))
- {
- avatar_name_cache_connection_map_t::iterator it = mGroupNameCacheConnections.find(id);
- if (it != mGroupNameCacheConnections.end())
- {
- if (it->second.connected())
- {
- it->second.disconnect();
- }
- mGroupNameCacheConnections.erase(it);
- }
- mGroupNameCacheConnections[id] = gCacheName->getGroup(id, boost::bind(&LLNameListCtrl::onGroupNameCache, this, _1, _2, item->getHandle()));
- }
- break;
- case SPECIAL:
- {
- item->setSpecialID(name_item.special_id());
- return item;
- }
- case INDIVIDUAL:
- {
- LLAvatarName av_name;
- if (id.isNull())
- {
- fullname = LLTrans::getString("AvatarNameNobody");
- }
- else if (LLAvatarNameCache::get(id, &av_name))
- {
- if (mShortNames)
- fullname = av_name.getDisplayName(true);
- else
- fullname = av_name.getCompleteName();
- }
- else
- {
- // ...schedule a callback
- avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id);
- if (it != mAvatarNameCacheConnections.end())
- {
- if (it->second.connected())
- {
- it->second.disconnect();
- }
- mAvatarNameCacheConnections.erase(it);
- }
- mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, prefix, item->getHandle()));
-
- if(mPendingLookupsRemaining <= 0)
- {
- // BAKER TODO:
- // We might get into a state where mPendingLookupsRemaining might
- // go negative. So just reset it right now and figure out if it's
- // possible later :)
- mPendingLookupsRemaining = 0;
- mNameListCompleteSignal(false);
- }
- mPendingLookupsRemaining++;
- }
- break;
- }
- case EXPERIENCE:
- // just use supplied name
- default:
- break;
- }
-
- // Append optional suffix.
- if (!suffix.empty())
- {
- fullname.append(suffix);
- }
-
- LLScrollListCell* cell = item->getColumn(mNameColumnIndex);
- if (cell)
- {
- cell->setValue(prefix + fullname);
- cell->setAltValue(name_item.alt_value());
- }
-
- dirtyColumns();
-
- // this column is resizable
- LLScrollListColumn* columnp = getColumn(mNameColumnIndex);
- if (columnp && columnp->mHeader)
- {
- columnp->mHeader->setHasResizableElement(true);
- }
-
- return item;
-}
-
-// public
-void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
-{
- // Find the item specified with agent_id.
- S32 idx = -1;
- for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)
- {
- LLScrollListItem* item = *it;
- LLUUID cur_id = isSpecialType() ? dynamic_cast<LLNameListItem*>(item)->getSpecialID() : item->getUUID();
- if (cur_id == agent_id)
- {
- idx = getItemIndex(item);
- break;
- }
- }
-
- // Remove it.
- if (idx >= 0)
- {
- selectNthItem(idx); // not sure whether this is needed, taken from previous implementation
- deleteSingleItem(idx);
-
- mPendingLookupsRemaining--;
- }
-}
-
-// public
-LLScrollListItem* LLNameListCtrl::getNameItemByAgentId(const LLUUID& agent_id)
-{
- for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)
- {
- LLScrollListItem* item = *it;
- if (item && item->getUUID() == agent_id)
- {
- return item;
- }
- }
- return NULL;
-}
-
-void LLNameListCtrl::selectItemBySpecialId(const LLUUID& special_id)
-{
- if (special_id.isNull())
- {
- return;
- }
-
- for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)
- {
- LLNameListItem* item = dynamic_cast<LLNameListItem*>(*it);
- if (item && item->getSpecialID() == special_id)
- {
- item->setSelected(true);
- break;
- }
- }
-}
-
-LLUUID LLNameListCtrl::getSelectedSpecialId()
-{
- LLNameListItem* item = dynamic_cast<LLNameListItem*>(getFirstSelected());
- if(item)
- {
- return item->getSpecialID();
- }
- return LLUUID();
-}
-
-void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
- const LLAvatarName& av_name,
- std::string suffix,
- std::string prefix,
- LLHandle<LLNameListItem> item)
-{
- avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id);
- if (it != mAvatarNameCacheConnections.end())
- {
- if (it->second.connected())
- {
- it->second.disconnect();
- }
- mAvatarNameCacheConnections.erase(it);
- }
-
- std::string name;
- if (mShortNames)
- name = av_name.getDisplayName();
- else
- name = av_name.getCompleteName();
-
- // Append optional suffix.
- if (!suffix.empty())
- {
- name.append(suffix);
- }
-
- if (!prefix.empty())
- {
- name.insert(0, prefix);
- }
-
- LLNameListItem* list_item = item.get();
- if (list_item && list_item->getUUID() == agent_id)
- {
- LLScrollListCell* cell = list_item->getColumn(mNameColumnIndex);
- if (cell)
- {
- cell->setValue(name);
- setNeedsSort();
- }
- }
-
- //////////////////////////////////////////////////////////////////////////
- // BAKER - FIX NameListCtrl
- //if (mPendingLookupsRemaining <= 0)
- {
- // We might get into a state where mPendingLookupsRemaining might
- // go negative. So just reset it right now and figure out if it's
- // possible later :)
- //mPendingLookupsRemaining = 0;
-
- mNameListCompleteSignal(true);
- }
- //else
- {
- // mPendingLookupsRemaining--;
- }
- //////////////////////////////////////////////////////////////////////////
-
- dirtyColumns();
-}
-
-void LLNameListCtrl::onGroupNameCache(const LLUUID& group_id, const std::string name, LLHandle<LLNameListItem> item)
-{
- avatar_name_cache_connection_map_t::iterator it = mGroupNameCacheConnections.find(group_id);
- if (it != mGroupNameCacheConnections.end())
- {
- if (it->second.connected())
- {
- it->second.disconnect();
- }
- mGroupNameCacheConnections.erase(it);
- }
-
- LLNameListItem* list_item = item.get();
- if (list_item && list_item->getUUID() == group_id)
- {
- LLScrollListCell* cell = list_item->getColumn(mNameColumnIndex);
- if (cell)
- {
- cell->setValue(name);
- setNeedsSort();
- }
- }
-
- dirtyColumns();
-}
-
-void LLNameListCtrl::updateColumns(bool force_update)
-{
- LLScrollListCtrl::updateColumns(force_update);
-
- if (!mNameColumn.empty())
- {
- LLScrollListColumn* name_column = getColumn(mNameColumn);
- if (name_column)
- {
- mNameColumnIndex = name_column->mIndex;
- }
- }
-}
-
-void LLNameListCtrl::sortByName(bool ascending)
-{
- sortByColumnIndex(mNameColumnIndex,ascending);
-}
+/** + * @file llnamelistctrl.cpp + * @brief A list of names, automatically refreshed from name cache. + * + * $LicenseInfo:firstyear=2003&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 "llnamelistctrl.h" + +#include <boost/tokenizer.hpp> + +#include "llavatarnamecache.h" +#include "llcachename.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "llfloatersnapshot.h" // gSnapshotFloaterView +#include "llinventory.h" +#include "llscrolllistitem.h" +#include "llscrolllistcell.h" +#include "llscrolllistcolumn.h" +#include "llsdparam.h" +#include "lltooltip.h" +#include "lltrans.h" + +static LLDefaultChildRegistry::Register<LLNameListCtrl> r("name_list"); + +static constexpr S32 info_icon_size = 16; + +void LLNameListCtrl::NameTypeNames::declareValues() +{ + declare("INDIVIDUAL", LLNameListCtrl::INDIVIDUAL); + declare("GROUP", LLNameListCtrl::GROUP); + declare("SPECIAL", LLNameListCtrl::SPECIAL); +} + +LLNameListCtrl::Params::Params() +: name_column(""), + allow_calling_card_drop("allow_calling_card_drop", false), + short_names("short_names", false) +{ +} + +LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p) +: LLScrollListCtrl(p), + mNameColumnIndex(p.name_column.column_index), + mNameColumn(p.name_column.column_name), + mAllowCallingCardDrop(p.allow_calling_card_drop), + mShortNames(p.short_names), + mPendingLookupsRemaining(0), + mHoverIconName("Info_Small"), + mNameListType(INDIVIDUAL) +{} + +// public +LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, + bool enabled, const std::string& suffix, const std::string& prefix) +{ + //LL_INFOS() << "LLNameListCtrl::addNameItem " << agent_id << LL_ENDL; + + NameItem item; + item.value = agent_id; + item.enabled = enabled; + item.target = INDIVIDUAL; + + return addNameItemRow(item, pos, suffix, prefix); +} + +// virtual, public +bool LLNameListCtrl::handleDragAndDrop( + S32 x, S32 y, MASK mask, + bool drop, + EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg) +{ + if (!mAllowCallingCardDrop) + { + return false; + } + + bool handled = false; + + if (cargo_type == DAD_CALLINGCARD) + { + if (drop) + { + LLInventoryItem* item = (LLInventoryItem *)cargo_data; + addNameItem(item->getCreatorUUID()); + } + + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + if (tooltip_msg.empty()) + { + if (!getToolTip().empty()) + { + tooltip_msg = getToolTip(); + } + else + { + // backwards compatable English tooltip (should be overridden in xml) + tooltip_msg.assign("Drag a calling card here\nto add a resident."); + } + } + } + + handled = true; + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLNameListCtrl " << getName() << LL_ENDL; + + return handled; +} + +void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience) +{ + if (isSpecialType()) + { + mIconClickedSignal(avatar_id); + return; + } + if(is_experience) + { + LLFloaterReg::showInstance("experience_profile", avatar_id, true); + return; + } + + if (is_group) + LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id)); + else + LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id)); +} + +void LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index ) +{ + S32 cur_index = getHighlightedItemInx(); + if (cur_index != target_index) + { + bool is_mouse_over_name_cell = false; + + S32 mouse_x, mouse_y; + LLUI::getInstance()->getMousePositionLocal(this, &mouse_x, &mouse_y); + + S32 column_index = getColumnIndexFromOffset(mouse_x); + LLScrollListItem* hit_item = hitItem(mouse_x, mouse_y); + if (hit_item && column_index == mNameColumnIndex) + { + // Get the name cell which is currently under the mouse pointer. + LLScrollListCell* hit_cell = hit_item->getColumn(column_index); + if (hit_cell) + { + is_mouse_over_name_cell = getCellRect(cur_index, column_index).pointInRect(mouse_x, mouse_y); + } + } + + // If the tool tip is visible and the mouse is over the currently highlighted item's name cell, + // we should not reset the highlighted item index i.e. set mHighlightedItem = -1 + // and should not increase the width of the text inside the cell because it may + // overlap the tool tip icon. + if (LLToolTipMgr::getInstance()->toolTipVisible() && is_mouse_over_name_cell) + return; + + if(0 <= cur_index && cur_index < (S32)getItemList().size()) + { + LLScrollListItem* item = getItemList()[cur_index]; + if (item) + { + LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex)); + if (cell) + cell->setTextWidth(cell->getTextWidth() + info_icon_size); + } + else + { + LL_WARNS() << "highlighted name list item is NULL" << LL_ENDL; + } + } + if(target_index != -1) + { + LLScrollListItem* item = getItemList()[target_index]; + LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex)); + if (item) + { + if (cell) + cell->setTextWidth(cell->getTextWidth() - info_icon_size); + } + else + { + LL_WARNS() << "target name item is NULL" << LL_ENDL; + } + } + } + + LLScrollListCtrl::mouseOverHighlightNthItem(target_index); +} + +//virtual +bool LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) +{ + bool handled = false; + S32 column_index = getColumnIndexFromOffset(x); + LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y)); + LLFloater* floater = gFloaterView->getParentFloater(this); + + + if (floater + && floater->isFrontmost() + && hit_item + && ((column_index == mNameColumnIndex) || isSpecialType())) + { + // ...this is the column with the avatar name + LLUUID item_id = isSpecialType() ? hit_item->getSpecialID() : hit_item->getUUID(); + if (item_id.notNull()) + { + // ...valid avatar id + + LLScrollListCell* hit_cell = hit_item->getColumn(column_index); + if (hit_cell) + { + S32 row_index = getItemIndex(hit_item); + LLRect cell_rect = getCellRect(row_index, isSpecialType() ? getNumColumns() - 1 : column_index); + // Convert rect local to screen coordinates + LLRect sticky_rect; + localRectToScreen(cell_rect, &sticky_rect); + + // Spawn at right side of cell + LLPointer<LLUIImage> icon = LLUI::getUIImage(mHoverIconName); + S32 screenX = sticky_rect.mRight - info_icon_size; + S32 screenY = sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight()) / 2; + LLCoordGL pos(screenX, screenY); + + LLFloater* snapshot_floatr = gSnapshotFloaterView->getFrontmostClosableFloater(); + if (!snapshot_floatr || !snapshot_floatr->getRect().pointInRect(screenX + icon->getWidth(), screenY)) + { + // Should we show a group or an avatar inspector? + bool is_group = hit_item->isGroup(); + bool is_experience = hit_item->isExperience(); + + LLToolTip::Params params; + params.background_visible(false); + params.click_callback(boost::bind(&LLNameListCtrl::showInspector, this, item_id, is_group, is_experience)); + params.delay_time(0.0f); // spawn instantly on hover + params.image(icon); + params.message(""); + params.padding(0); + params.pos(pos); + params.sticky_rect(sticky_rect); + + LLToolTipMgr::getInstance()->show(params); + handled = true; + } + } + } + } + if (!handled) + { + handled = LLScrollListCtrl::handleToolTip(x, y, mask); + } + return handled; +} + +// virtual +bool LLNameListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y)); + LLFloater* floater = gFloaterView->getParentFloater(this); + if (floater && floater->isFrontmost() && hit_item) + { + if(hit_item->isGroup()) + { + ContextMenuType prev_menu = getContextMenuType(); + setContextMenu(MENU_GROUP); + bool handled = LLScrollListCtrl::handleRightMouseDown(x, y, mask); + setContextMenu(prev_menu); + return handled; + } + } + return LLScrollListCtrl::handleRightMouseDown(x, y, mask); +} + +// public +void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos, + bool enabled) +{ + NameItem item; + item.value = group_id; + item.enabled = enabled; + item.target = GROUP; + + addNameItemRow(item, pos); +} + +// public +void LLNameListCtrl::addGroupNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos) +{ + item.target = GROUP; + addNameItemRow(item, pos); +} + +LLScrollListItem* LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos) +{ + item.target = INDIVIDUAL; + return addNameItemRow(item, pos); +} + +LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata) +{ + LLNameListCtrl::NameItem item_params; + LLParamSDParser parser; + parser.readSD(element, item_params); + item_params.userdata = userdata; + return addNameItemRow(item_params, pos); +} + + +LLScrollListItem* LLNameListCtrl::addNameItemRow( + const LLNameListCtrl::NameItem& name_item, + EAddPosition pos, + const std::string& suffix, + const std::string& prefix) +{ + LLUUID id = name_item.value().asUUID(); + LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP, name_item.target() == EXPERIENCE); + + if (!item) return NULL; + + LLScrollListCtrl::addRow(item, name_item, pos); + + // use supplied name by default + std::string fullname = name_item.name; + + switch(name_item.target) + { + case GROUP: + if (!gCacheName->getGroupName(id, fullname)) + { + avatar_name_cache_connection_map_t::iterator it = mGroupNameCacheConnections.find(id); + if (it != mGroupNameCacheConnections.end()) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + mGroupNameCacheConnections.erase(it); + } + mGroupNameCacheConnections[id] = gCacheName->getGroup(id, boost::bind(&LLNameListCtrl::onGroupNameCache, this, _1, _2, item->getHandle())); + } + break; + case SPECIAL: + { + item->setSpecialID(name_item.special_id()); + return item; + } + case INDIVIDUAL: + { + LLAvatarName av_name; + if (id.isNull()) + { + fullname = LLTrans::getString("AvatarNameNobody"); + } + else if (LLAvatarNameCache::get(id, &av_name)) + { + if (mShortNames) + fullname = av_name.getDisplayName(true); + else + fullname = av_name.getCompleteName(); + } + else + { + // ...schedule a callback + avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(id); + if (it != mAvatarNameCacheConnections.end()) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + mAvatarNameCacheConnections.erase(it); + } + mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, prefix, item->getHandle())); + + if(mPendingLookupsRemaining <= 0) + { + // BAKER TODO: + // We might get into a state where mPendingLookupsRemaining might + // go negative. So just reset it right now and figure out if it's + // possible later :) + mPendingLookupsRemaining = 0; + mNameListCompleteSignal(false); + } + mPendingLookupsRemaining++; + } + break; + } + case EXPERIENCE: + // just use supplied name + default: + break; + } + + // Append optional suffix. + if (!suffix.empty()) + { + fullname.append(suffix); + } + + LLScrollListCell* cell = item->getColumn(mNameColumnIndex); + if (cell) + { + cell->setValue(prefix + fullname); + cell->setAltValue(name_item.alt_value()); + } + + dirtyColumns(); + + // this column is resizable + LLScrollListColumn* columnp = getColumn(mNameColumnIndex); + if (columnp && columnp->mHeader) + { + columnp->mHeader->setHasResizableElement(true); + } + + return item; +} + +// public +void LLNameListCtrl::removeNameItem(const LLUUID& agent_id) +{ + // Find the item specified with agent_id. + S32 idx = -1; + for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) + { + LLScrollListItem* item = *it; + LLUUID cur_id = isSpecialType() ? dynamic_cast<LLNameListItem*>(item)->getSpecialID() : item->getUUID(); + if (cur_id == agent_id) + { + idx = getItemIndex(item); + break; + } + } + + // Remove it. + if (idx >= 0) + { + selectNthItem(idx); // not sure whether this is needed, taken from previous implementation + deleteSingleItem(idx); + + mPendingLookupsRemaining--; + } +} + +// public +LLScrollListItem* LLNameListCtrl::getNameItemByAgentId(const LLUUID& agent_id) +{ + for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) + { + LLScrollListItem* item = *it; + if (item && item->getUUID() == agent_id) + { + return item; + } + } + return NULL; +} + +void LLNameListCtrl::selectItemBySpecialId(const LLUUID& special_id) +{ + if (special_id.isNull()) + { + return; + } + + for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) + { + LLNameListItem* item = dynamic_cast<LLNameListItem*>(*it); + if (item && item->getSpecialID() == special_id) + { + item->setSelected(true); + break; + } + } +} + +LLUUID LLNameListCtrl::getSelectedSpecialId() +{ + LLNameListItem* item = dynamic_cast<LLNameListItem*>(getFirstSelected()); + if(item) + { + return item->getSpecialID(); + } + return LLUUID(); +} + +void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, + const LLAvatarName& av_name, + std::string suffix, + std::string prefix, + LLHandle<LLNameListItem> item) +{ + avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.find(agent_id); + if (it != mAvatarNameCacheConnections.end()) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + mAvatarNameCacheConnections.erase(it); + } + + std::string name; + if (mShortNames) + name = av_name.getDisplayName(); + else + name = av_name.getCompleteName(); + + // Append optional suffix. + if (!suffix.empty()) + { + name.append(suffix); + } + + if (!prefix.empty()) + { + name.insert(0, prefix); + } + + LLNameListItem* list_item = item.get(); + if (list_item && list_item->getUUID() == agent_id) + { + LLScrollListCell* cell = list_item->getColumn(mNameColumnIndex); + if (cell) + { + cell->setValue(name); + setNeedsSort(); + } + } + + ////////////////////////////////////////////////////////////////////////// + // BAKER - FIX NameListCtrl + //if (mPendingLookupsRemaining <= 0) + { + // We might get into a state where mPendingLookupsRemaining might + // go negative. So just reset it right now and figure out if it's + // possible later :) + //mPendingLookupsRemaining = 0; + + mNameListCompleteSignal(true); + } + //else + { + // mPendingLookupsRemaining--; + } + ////////////////////////////////////////////////////////////////////////// + + dirtyColumns(); +} + +void LLNameListCtrl::onGroupNameCache(const LLUUID& group_id, const std::string name, LLHandle<LLNameListItem> item) +{ + avatar_name_cache_connection_map_t::iterator it = mGroupNameCacheConnections.find(group_id); + if (it != mGroupNameCacheConnections.end()) + { + if (it->second.connected()) + { + it->second.disconnect(); + } + mGroupNameCacheConnections.erase(it); + } + + LLNameListItem* list_item = item.get(); + if (list_item && list_item->getUUID() == group_id) + { + LLScrollListCell* cell = list_item->getColumn(mNameColumnIndex); + if (cell) + { + cell->setValue(name); + setNeedsSort(); + } + } + + dirtyColumns(); +} + +void LLNameListCtrl::updateColumns(bool force_update) +{ + LLScrollListCtrl::updateColumns(force_update); + + if (!mNameColumn.empty()) + { + LLScrollListColumn* name_column = getColumn(mNameColumn); + if (name_column) + { + mNameColumnIndex = name_column->mIndex; + } + } +} + +void LLNameListCtrl::sortByName(bool ascending) +{ + sortByColumnIndex(mNameColumnIndex,ascending); +} |