summaryrefslogtreecommitdiff
path: root/indra/newview/llavatarlist.cpp
diff options
context:
space:
mode:
authorMark Palange (Mani) <palange@lindenlab.com>2009-10-02 10:35:42 -0700
committerMark Palange (Mani) <palange@lindenlab.com>2009-10-02 10:35:42 -0700
commit4d53e235c2445b820bb0ae7303b269648dd86037 (patch)
treec1ab3643cf257099822e7a0e1e832d76813555f6 /indra/newview/llavatarlist.cpp
parent80f27013b2d2a7ca6509db033c8f0c31562e04c7 (diff)
parentdde2153014cd7d7b8fa704f7067a41344bfbb1c2 (diff)
merge of latest viewer/viewer-20
Diffstat (limited to 'indra/newview/llavatarlist.cpp')
-rw-r--r--indra/newview/llavatarlist.cpp546
1 files changed, 149 insertions, 397 deletions
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 2e64c10bb2..36f9780ad0 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -37,481 +37,233 @@
// newview
#include "llcallingcard.h" // for LLAvatarTracker
#include "llcachename.h"
-#include "lloutputmonitorctrl.h"
#include "llvoiceclient.h"
static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
-static LLDefaultChildRegistry::Register<LLAvatarListTmp> r_tmp("avatar_list_tmp");
-static const std::string COMMENT_TEXTBOX = "comment_text";
+// Maximum number of avatars that can be added to a list in one pass.
+// Used to limit time spent for avatar list update per frame.
+static const unsigned ADD_LIMIT = 50;
+
+static bool findInsensitive(std::string haystack, const std::string& needle_upper)
+{
+ LLStringUtil::toUpper(haystack);
+ return haystack.find(needle_upper) != std::string::npos;
+}
+
+
+//comparators
+static const LLAvatarItemNameComparator NAME_COMPARATOR;
+static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_COMPARATOR);
LLAvatarList::Params::Params()
:
- volume_column_width("volume_column_width", 0)
- , online_go_first("online_go_first", true)
+volume_column_width("volume_column_width", 0)
+, online_go_first("online_go_first", true)
{
- draw_heading = true;
- draw_stripes = false;
- multi_select = false;
- column_padding = 0;
- search_column = COL_NAME;
- sort_column = COL_NAME;
}
+
+
LLAvatarList::LLAvatarList(const Params& p)
-: LLScrollListCtrl(p)
- , mHaveVolumeColumn(p.volume_column_width > 0)
- , mOnlineGoFirst(p.online_go_first)
+: LLFlatListView(p)
+, mOnlineGoFirst(p.online_go_first)
+, mContextMenu(NULL)
+, mDirty(true) // to force initial update
{
- setCommitOnSelectionChange(TRUE); // there's no such param in LLScrollListCtrl::Params
-
- // display a context menu appropriate for a list of avatar names
- setContextMenu(LLScrollListCtrl::MENU_AVATAR);
-
- // "volume" column
- {
- LLScrollListColumn::Params col_params;
- col_params.name = "volume";
- col_params.header.label = "Volume"; // *TODO: localize or remove the header
- col_params.width.pixel_width = p.volume_column_width;
- addColumn(col_params);
- }
-
- // "name" column
- {
- LLScrollListColumn::Params col_params;
- col_params.name = "name";
- col_params.header.label = "Name"; // *TODO: localize or remove the header
- col_params.width.dynamic_width = true;
- addColumn(col_params);
- }
-
- // "online status" column
- {
- LLScrollListColumn::Params col_params;
- col_params.name = "online";
- col_params.header.label = "Online"; // *TODO: localize or remove the header
- col_params.width.pixel_width = 0; // invisible column
- addColumn(col_params);
- }
-
-
- // invisible "id" column
- {
- LLScrollListColumn::Params col_params;
- col_params.name = "id";
- col_params.header.label = "ID"; // *TODO: localize or remove the header
- col_params.width.pixel_width = 0;
- addColumn(col_params);
- }
-
- // Primary sort = online status, secondary sort = name
- // The corresponding parameters don't work because we create columns dynamically.
- sortByColumnIndex(COL_NAME, TRUE);
- if (mOnlineGoFirst)
- sortByColumnIndex(COL_ONLINE, FALSE);
- setSearchColumn(COL_NAME);
+ setCommitOnSelectionChange(true);
+
+ // Set default sort order.
+ setComparator(&NAME_COMPARATOR);
}
// virtual
void LLAvatarList::draw()
{
- LLScrollListCtrl::draw();
- if (mHaveVolumeColumn)
- {
- updateVolume();
- }
-}
+ if (mDirty)
+ refresh();
-std::vector<LLUUID> LLAvatarList::getSelectedIDs()
-{
- LLUUID selected_id;
- std::vector<LLUUID> avatar_ids;
- std::vector<LLScrollListItem*> selected = getAllSelected();
- for(std::vector<LLScrollListItem*>::iterator itr = selected.begin(); itr != selected.end(); ++itr)
- {
- avatar_ids.push_back((*itr)->getUUID());
- }
- return avatar_ids;
+ LLFlatListView::draw();
}
-void LLAvatarList::addItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
+void LLAvatarList::setNameFilter(const std::string& filter)
{
- std::string fullname;
-
- // Populate list item.
- LLSD element;
- element["id"] = id;
-
- // Update volume column (if we have one)
- {
- std::string icon = mHaveVolumeColumn ? getVolumeIcon(id) : "";
- LLSD& volume_column = element["columns"][COL_VOLUME];
- volume_column["column"] = "volume";
- volume_column["type"] = "icon";
- volume_column["value"] = icon;
- }
-
- LLSD& friend_column = element["columns"][COL_NAME];
- friend_column["column"] = "name";
- friend_column["value"] = name;
-
- LLSD& online_column = element["columns"][COL_ONLINE];
- online_column["column"] = "online";
- online_column["value"] = is_bold ? "1" : "0";
-
- LLScrollListItem* new_itemp = addElement(element, pos);
-
- // Indicate buddy online status.
- // (looks like parsing font parameters from LLSD is broken)
- if (is_bold)
+ if (mNameFilter != filter)
{
- LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(new_itemp->getColumn(COL_NAME));
- if (name_textp)
- name_textp->setFontStyle(LLFontGL::BOLD);
- else
- {
- llwarns << "Name column not found" << llendl;
- }
+ mNameFilter = filter;
+ setDirty();
}
}
-static bool findInsensitive(std::string haystack, const std::string& needle_upper)
+void LLAvatarList::sortByName()
{
- LLStringUtil::toUpper(haystack);
- return haystack.find(needle_upper) != std::string::npos;
+ setComparator(&NAME_COMPARATOR);
+ sort();
}
-BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::string& name_filter)
+//////////////////////////////////////////////////////////////////////////
+// PROTECTED SECTION
+//////////////////////////////////////////////////////////////////////////
+
+void LLAvatarList::refresh()
{
- BOOL have_names = TRUE;
-
+ bool have_names = TRUE;
+ bool add_limit_exceeded = false;
+ bool modified = false;
+ bool have_filter = !mNameFilter.empty();
+
// Save selection.
- std::vector<LLUUID> selected_ids = getSelectedIDs();
- LLUUID current_id = getCurrentID();
- S32 pos = getScrollPos();
-
- std::vector<LLUUID>::const_iterator buddy_it = all_buddies.begin();
- deleteAllItems();
- for(; buddy_it != all_buddies.end(); ++buddy_it)
- {
- std::string name;
- const LLUUID& buddy_id = *buddy_it;
- have_names &= gCacheName->getFullName(buddy_id, name);
- if (name_filter != LLStringUtil::null && !findInsensitive(name, name_filter))
- continue;
- addItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
- }
+ std::vector<LLUUID> selected_ids;
+ getSelectedUUIDs(selected_ids);
+ LLUUID current_id = getSelectedUUID();
- // Changed item in place, need to request sort and update columns
- // because we might have changed data in a column on which the user
- // has already sorted. JC
- updateSort();
+ // Determine what to add and what to remove.
+ std::vector<LLUUID> added, removed;
+ LLAvatarList::computeDifference(getIDs(), added, removed);
- // re-select items
- selectMultiple(selected_ids);
- setCurrentByID(current_id);
-#if 0
- // Restore selection.
- if(selected_ids.size() > 0)
+ // Handle added items.
+ unsigned nadded = 0;
+ for (std::vector<LLUUID>::const_iterator it=added.begin(); it != added.end(); it++)
{
- // only non-null if friends was already found. This may fail,
- // but we don't really care here, because refreshUI() will
- // clean up the interface.
- for(std::vector<LLUUID>::iterator itr = selected_ids.begin(); itr != selected_ids.end(); ++itr)
+ std::string name;
+ const LLUUID& buddy_id = *it;
+ have_names &= (bool)gCacheName->getFullName(buddy_id, name);
+ if (!have_filter || findInsensitive(name, mNameFilter))
{
- setSelectedByValue(*itr, true);
+ if (nadded >= ADD_LIMIT)
+ {
+ add_limit_exceeded = true;
+ break;
+ }
+ else
+ {
+ addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
+ modified = true;
+ nadded++;
+ }
}
}
-#endif
- setScrollPos(pos);
-
- updateLineHeight();
- LLRect rect = getRequiredRect();
-
- LLSD params;
- params["action"] = "size_changes";
- params["width"] = rect.getWidth();
- params["height"] = llmax(rect.getHeight(),20) + 5;
-
- getParent()->notifyParent(params);
-
- return have_names;
-}
-
-// static
-std::string LLAvatarList::getVolumeIcon(const LLUUID& id)
-{
- //
- // Determine icon appropriate for the current avatar volume.
- //
- // *TODO: remove this in favor of LLOutputMonitorCtrl
- // when ListView widget is implemented
- // which is capable of containing arbitrary widgets.
- //
- static LLOutputMonitorCtrl::Params default_monitor_params(LLUICtrlFactory::getDefaultParams<LLOutputMonitorCtrl>());
- bool muted = gVoiceClient->getIsModeratorMuted(id) || gVoiceClient->getOnMuteList(id);
- F32 power = gVoiceClient->getCurrentPower(id);
- std::string icon;
- if (muted)
- {
- icon = default_monitor_params.image_mute.name;
- }
- else if (power == 0.f)
- {
- icon = default_monitor_params.image_off.name;
- }
- else if (power < LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
+ // Handle removed items.
+ for (std::vector<LLUUID>::const_iterator it=removed.begin(); it != removed.end(); it++)
{
- S32 icon_image_idx = llmin(2, llfloor((power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f));
- switch(icon_image_idx)
- {
- default:
- case 0:
- icon = default_monitor_params.image_on.name;
- break;
- case 1:
- icon = default_monitor_params.image_level_1.name;
- break;
- case 2:
- icon = default_monitor_params.image_level_2.name;
- break;
- }
+ removeItemByUUID(*it);
+ modified = true;
}
- else
- {
- // overdriven
- icon = default_monitor_params.image_level_3.name;
- }
-
- return icon;
-}
-
-// Update volume column for all list rows.
-void LLAvatarList::updateVolume()
-{
- item_list& items = getItemList();
- for (item_list::iterator item_it = items.begin();
- item_it != items.end();
- ++item_it)
+ // Handle filter.
+ if (have_filter)
{
- LLScrollListItem* itemp = (*item_it);
- LLUUID speaker_id = itemp->getUUID();
+ std::vector<LLSD> cur_values;
+ getValues(cur_values);
- LLScrollListCell* icon_cell = itemp->getColumn(COL_VOLUME);
- if (icon_cell)
- icon_cell->setValue(getVolumeIcon(speaker_id));
+ for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
+ {
+ std::string name;
+ const LLUUID& buddy_id = it->asUUID();
+ have_names &= (bool)gCacheName->getFullName(buddy_id, name);
+ if (!findInsensitive(name, mNameFilter))
+ {
+ removeItemByUUID(buddy_id);
+ modified = true;
+ }
+ }
}
-}
-
-
-
-
-#include "llavatarlistitem.h"
-
-LLAvatarListTmp::Params::Params()
-:
-volume_column_width("volume_column_width", 0)
-, online_go_first("online_go_first", true)
-{
-}
-
+ // Changed item in place, need to request sort and update columns
+ // because we might have changed data in a column on which the user
+ // has already sorted. JC
+ sort();
-LLAvatarListTmp::LLAvatarListTmp(const Params& p)
-: LLFlatListView(p)
-, mHaveVolumeColumn(p.volume_column_width > 0)
-, mOnlineGoFirst(p.online_go_first)
-{
- LLRect item_list_rect = getLocalRect();
- item_list_rect.stretch( -getBorderWidth());
-
- LLTextBox::Params text_p;
- text_p.name(COMMENT_TEXTBOX);
- text_p.border_visible(false);
- text_p.rect(item_list_rect);
- text_p.follows.flags(FOLLOWS_ALL);
- addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
-}
+ // re-select items
+ // selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need
+ selectItemByUUID(current_id);
-// virtual
-void LLAvatarListTmp::draw()
-{
- LLFlatListView::draw();
- if (mHaveVolumeColumn)
- {
- updateVolume();
- }
+ // If the name filter is specified and the names are incomplete,
+ // we need to re-update when the names are complete so that
+ // the filter can be applied correctly.
+ //
+ // Otherwise, if we have no filter then no need to update again
+ // because the items will update their names.
+ bool dirty = add_limit_exceeded || (have_filter && !have_names);
+ setDirty(dirty);
+
+ // Commit if we've added/removed items.
+ if (modified)
+ onCommit();
}
-std::vector<LLUUID> LLAvatarListTmp::getSelectedIDs()
-{
- LLUUID selected_id;
- std::vector<LLUUID> avatar_ids;
-
- getSelectedUUIDs(avatar_ids);
- return avatar_ids;
-}
-
-void LLAvatarListTmp::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
+void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
- item->showStatus(true);
+ item->showStatus(false);
item->showInfoBtn(true);
item->showSpeakingIndicator(true);
item->setName(name);
item->setAvatarId(id);
+ item->setContextMenu(mContextMenu);
item->childSetVisible("info_btn", false);
addItem(item, id, pos);
-
- setCommentVisible(false);
}
-BOOL LLAvatarListTmp::update(const std::vector<LLUUID>& all_buddies, const std::string& name_filter)
+void LLAvatarList::computeDifference(
+ const std::vector<LLUUID>& vnew_unsorted,
+ std::vector<LLUUID>& vadded,
+ std::vector<LLUUID>& vremoved)
{
- BOOL have_names = TRUE;
-
- // Save selection.
- std::vector<LLUUID> selected_ids = getSelectedIDs();
- LLUUID current_id = getSelectedUUID();
- LLRect pos = getScrolledViewRect();
+ std::vector<LLUUID> vcur;
+ std::vector<LLUUID> vnew = vnew_unsorted;
- std::vector<LLUUID>::const_iterator buddy_it = all_buddies.begin();
- clear();
- for(; buddy_it != all_buddies.end(); ++buddy_it)
+ // Convert LLSDs to LLUUIDs.
{
- std::string name;
- const LLUUID& buddy_id = *buddy_it;
- have_names &= gCacheName->getFullName(buddy_id, name);
- if (name_filter != LLStringUtil::null && !findInsensitive(name, name_filter))
- continue;
- addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
- }
-
- // Changed item in place, need to request sort and update columns
- // because we might have changed data in a column on which the user
- // has already sorted. JC
- // updateSort(); // TODO: implement sorting
+ std::vector<LLSD> vcur_values;
+ getValues(vcur_values);
- // re-select items
- // selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need
- selectItemByUUID(current_id);
-
- scrollToShowRect(pos);
-
-
- setCommentVisible(false);
-
- return have_names;
-}
-
-
-const LLUUID LLAvatarListTmp::getCurrentID() const
-{
- return getSelectedUUID();
-}
+ for (size_t i=0; i<vcur_values.size(); i++)
+ vcur.push_back(vcur_values[i].asUUID());
+ }
-void LLAvatarListTmp::setCommentText(const std::string& comment_text)
-{
- getChild<LLTextBox>(COMMENT_TEXTBOX)->setValue(comment_text);
-}
+ std::sort(vcur.begin(), vcur.end());
+ std::sort(vnew.begin(), vnew.end());
+ std::vector<LLUUID>::iterator it;
+ size_t maxsize = llmax(vcur.size(), vnew.size());
+ vadded.resize(maxsize);
+ vremoved.resize(maxsize);
-//////////////////////////////////////////////////////////////////////////
-// PROTECTED SECTION
-//////////////////////////////////////////////////////////////////////////
+ // what to remove
+ it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin());
+ vremoved.erase(it, vremoved.end());
-// virtual overridden
-bool LLAvatarListTmp::removeItemPair(item_pair_t* item_pair)
-{
- bool removed = LLFlatListView::removeItemPair(item_pair);
- setCommentVisible(size() == 0);
- return removed;
+ // what to add
+ it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin());
+ vadded.erase(it, vadded.end());
}
-
-//////////////////////////////////////////////////////////////////////////
-// PRIVATE SECTION
-//////////////////////////////////////////////////////////////////////////
-
-// static
-std::string LLAvatarListTmp::getVolumeIcon(const LLUUID& id)
+bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
{
- //
- // Determine icon appropriate for the current avatar volume.
- //
- // *TODO: remove this in favor of LLOutputMonitorCtrl
- // when ListView widget is implemented
- // which is capable of containing arbitrary widgets.
- //
- static LLOutputMonitorCtrl::Params default_monitor_params(LLUICtrlFactory::getDefaultParams<LLOutputMonitorCtrl>());
- bool muted = gVoiceClient->getIsModeratorMuted(id) || gVoiceClient->getOnMuteList(id);
- F32 power = gVoiceClient->getCurrentPower(id);
- std::string icon;
-
- if (muted)
- {
- icon = default_monitor_params.image_mute.name;
- }
- else if (power == 0.f)
- {
- icon = default_monitor_params.image_off.name;
- }
- else if (power < LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
- {
- S32 icon_image_idx = llmin(2, llfloor((power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f));
- switch(icon_image_idx)
- {
- default:
- case 0:
- icon = default_monitor_params.image_on.name;
- break;
- case 1:
- icon = default_monitor_params.image_level_1.name;
- break;
- case 2:
- icon = default_monitor_params.image_level_2.name;
- break;
- }
- }
- else
+ const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);
+ const LLAvatarListItem* avatar_item2 = dynamic_cast<const LLAvatarListItem*>(item2);
+
+ if (!avatar_item1 || !avatar_item2)
{
- // overdriven
- icon = default_monitor_params.image_level_3.name;
+ llerror("item1 and item2 cannot be null", 0);
+ return true;
}
- return icon;
+ return doCompare(avatar_item1, avatar_item2);
}
-// Update volume column for all list rows.
-void LLAvatarListTmp::updateVolume()
+bool LLAvatarItemNameComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
{
- // TODO: implement via Listener
- /*
- item_list& items = getItemList();
+ std::string name1 = avatar_item1->getAvatarName();
+ std::string name2 = avatar_item2->getAvatarName();
- for (item_list::iterator item_it = items.begin();
- item_it != items.end();
- ++item_it)
- {
- LLScrollListItem* itemp = (*item_it);
- LLUUID speaker_id = itemp->getUUID();
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
- LLScrollListCell* icon_cell = itemp->getColumn(COL_VOLUME);
- if (icon_cell)
- icon_cell->setValue(getVolumeIcon(speaker_id));
- }
- */
+ return name1 < name2;
}
-
-void LLAvatarListTmp::setCommentVisible(bool visible) const
-{
- getChildView(COMMENT_TEXTBOX)->setVisible(visible);
-}
-
-// EOF