summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorandreykproductengine <akleshchev@productengine.com>2016-09-26 21:29:20 +0300
committerandreykproductengine <akleshchev@productengine.com>2016-09-26 21:29:20 +0300
commitb7b98918eb36a1b69ef987a0b1fe8861a39b25b9 (patch)
tree9c0f8d258534adf11772e0b21b3c7aa368e8716d /indra
parentb941de80dbe15a20a0eaea795d1282cf36306c30 (diff)
MAINT-4950 Appearance panel performance improvements.
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llflatlistview.cpp114
-rw-r--r--indra/llui/llflatlistview.h11
-rw-r--r--indra/newview/llfilteredwearablelist.cpp5
-rw-r--r--indra/newview/llfilteredwearablelist.h5
-rw-r--r--indra/newview/llinventoryitemslist.cpp207
-rw-r--r--indra/newview/llinventoryitemslist.h28
-rw-r--r--indra/newview/llpaneloutfitedit.cpp4
-rw-r--r--indra/newview/llwearableitemslist.cpp24
-rw-r--r--indra/newview/llwearableitemslist.h2
9 files changed, 289 insertions, 111 deletions
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 299f5e42d4..4729eb4023 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -105,6 +105,81 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*
return true;
}
+bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= true*/)
+{
+ if (!mItemComparator)
+ {
+ LL_WARNS_ONCE() << "No comparator specified for inserting FlatListView items." << LL_ENDL;
+ return false;
+ }
+ if (panel_list.size() == 0)
+ {
+ return false;
+ }
+
+ // presort list so that it will be easier to sort elements into mItemPairs
+ panel_list.sort(ComparatorAdaptor(*mItemComparator));
+
+ pairs_const_iterator_t new_pair_it = panel_list.begin();
+ item_pair_t* new_pair = *new_pair_it;
+ pairs_iterator_t pair_it = mItemPairs.begin();
+ item_pair_t* item_pair = *pair_it;
+
+ // sort panel_list into mItemPars
+ while (new_pair_it != panel_list.end() && pair_it != mItemPairs.end())
+ {
+ if (!new_pair->first || new_pair->first->getParent() == mItemsPanel)
+ {
+ // iterator already used or we are reusing existing panel
+ new_pair_it++;
+ new_pair = *new_pair_it;
+ }
+ else if (mItemComparator->compare(new_pair->first, item_pair->first))
+ {
+ LLPanel* panel = new_pair->first;
+
+ mItemPairs.insert(pair_it, new_pair);
+ mItemsPanel->addChild(panel);
+
+ //_4 is for MASK
+ panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4));
+ // Children don't accept the focus
+ panel->setTabStop(false);
+ }
+ else
+ {
+ pair_it++;
+ item_pair = *pair_it;
+ }
+ }
+
+ // Add what is left of panel_list into the end of mItemPairs.
+ for (; new_pair_it != panel_list.end(); ++new_pair_it)
+ {
+ item_pair_t* item_pair = *new_pair_it;
+ LLPanel *panel = item_pair->first;
+ if (panel && panel->getParent() != mItemsPanel)
+ {
+ mItemPairs.push_back(item_pair);
+ mItemsPanel->addChild(panel);
+
+ //_4 is for MASK
+ panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4));
+ // Children don't accept the focus
+ panel->setTabStop(false);
+ }
+ }
+
+ if (rearrange)
+ {
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ }
+ return true;
+}
+
bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value /*= LLUUID::null*/)
{
@@ -1289,6 +1364,28 @@ void LLFlatListViewEx::setFilterSubString(const std::string& filter_str)
}
}
+void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
+{
+ if (!item) return;
+
+ // 0 signifies that filter is matched,
+ // i.e. we don't hide items that don't support 'match_filter' action, separators etc.
+ if (0 == item->notify(action))
+ {
+ mHasMatchedItems = true;
+ item->setVisible(true);
+ }
+ else
+ {
+ // TODO: implement (re)storing of current selection.
+ if (!mForceShowingUnmatchedItems)
+ {
+ selectItem(item, false);
+ }
+ item->setVisible(mForceShowingUnmatchedItems);
+ }
+}
+
void LLFlatListViewEx::filterItems()
{
typedef std::vector <LLPanel*> item_panel_list_t;
@@ -1309,22 +1406,7 @@ void LLFlatListViewEx::filterItems()
iter != iter_end; ++iter)
{
LLPanel* pItem = (*iter);
- // 0 signifies that filter is matched,
- // i.e. we don't hide items that don't support 'match_filter' action, separators etc.
- if (0 == pItem->notify(action))
- {
- mHasMatchedItems = true;
- pItem->setVisible(true);
- }
- else
- {
- // TODO: implement (re)storing of current selection.
- if(!mForceShowingUnmatchedItems)
- {
- selectItem(pItem, false);
- }
- pItem->setVisible(mForceShowingUnmatchedItems);
- }
+ updateItemVisibility(pItem, action);
}
sort();
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 92bf429031..230ea200d8 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -351,6 +351,8 @@ protected:
virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange);
+ bool addItemPairs(pairs_list_t panel_list, bool rearrange = true);
+
/**
* Notify parent about changed size of internal controls with "size_changes" action
*
@@ -480,6 +482,7 @@ public:
* Sets up new filter string and filters the list.
*/
void setFilterSubString(const std::string& filter_str);
+ std::string getFilterSubString() { return mFilterSubString; }
/**
* Filters the list, rearranges and notifies parent about shape changes.
@@ -503,6 +506,14 @@ protected:
*/
void updateNoItemsMessage(const std::string& filter_string);
+ /**
+ * Applies visibility acording to action and LLFlatListView settings.
+ *
+ * @param item - item we are changing
+ * @param item - action - parameters to determin visibility from
+ */
+ void updateItemVisibility(LLPanel* item, const LLSD &action);
+
private:
std::string mNoFilteredItemsMsg;
std::string mNoItemsMsg;
diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp
index a29ccf2b6d..f2af9b5300 100644
--- a/indra/newview/llfilteredwearablelist.cpp
+++ b/indra/newview/llfilteredwearablelist.cpp
@@ -93,4 +93,9 @@ void LLFilteredWearableListManager::populateList()
mWearableList->refreshList(item_array);
}
+void LLFilteredWearableListManager::holdProgress()
+{
+ mWearableList->setForceRefresh(false);
+}
+
// EOF
diff --git a/indra/newview/llfilteredwearablelist.h b/indra/newview/llfilteredwearablelist.h
index c21458ca98..f44ab1466f 100644
--- a/indra/newview/llfilteredwearablelist.h
+++ b/indra/newview/llfilteredwearablelist.h
@@ -56,6 +56,11 @@ public:
*/
void populateList();
+ /**
+ * Drop operation
+ */
+ void holdProgress();
+
private:
LLInventoryItemsList* mWearableList;
LLInventoryCollectFunctor* mCollector;
diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp
index 36e1cc97d1..1dc1aa395e 100644
--- a/indra/newview/llinventoryitemslist.cpp
+++ b/indra/newview/llinventoryitemslist.cpp
@@ -45,7 +45,7 @@ LLInventoryItemsList::Params::Params()
LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p)
: LLFlatListViewEx(p)
-, mNeedsRefresh(false)
+, mRefreshState(REFRESH_COMPLETE)
, mForceRefresh(false)
{
// TODO: mCommitOnSelectionChange is set to "false" in LLFlatListView
@@ -66,13 +66,13 @@ LLInventoryItemsList::~LLInventoryItemsList()
void LLInventoryItemsList::refreshList(const LLInventoryModel::item_array_t item_array)
{
- getIDs().clear();
+ getIDs().clear();
LLInventoryModel::item_array_t::const_iterator it = item_array.begin();
for( ; item_array.end() != it; ++it)
{
getIDs().push_back((*it)->getUUID());
}
- mNeedsRefresh = true;
+ mRefreshState = REFRESH_ALL;
}
boost::signals2::connection LLInventoryItemsList::setRefreshCompleteCallback(const commit_signal_t::slot_type& cb)
@@ -113,9 +113,9 @@ void LLInventoryItemsList::updateSelection()
void LLInventoryItemsList::doIdle()
{
- if (!mNeedsRefresh) return;
+ if (mRefreshState == REFRESH_COMPLETE) return;
- if (isInVisibleChain() || mForceRefresh)
+ if (isInVisibleChain() || mForceRefresh )
{
refresh();
@@ -137,54 +137,130 @@ LLTrace::BlockTimerStatHandle FTM_INVENTORY_ITEMS_REFRESH("Inventory List Refres
void LLInventoryItemsList::refresh()
{
- LL_RECORD_BLOCK_TIME(FTM_INVENTORY_ITEMS_REFRESH);
- static const unsigned ADD_LIMIT = 20;
-
- uuid_vec_t added_items;
- uuid_vec_t removed_items;
-
- computeDifference(getIDs(), added_items, removed_items);
-
- bool add_limit_exceeded = false;
- unsigned int nadded = 0;
-
- uuid_vec_t::const_iterator it = added_items.begin();
- for( ; added_items.end() != it; ++it)
- {
- if(nadded >= ADD_LIMIT)
- {
- add_limit_exceeded = true;
- break;
- }
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- // Do not rearrange items on each adding, let's do that on filter call
- llassert(item);
- if (item)
- {
- addNewItem(item, false);
- ++nadded;
- }
- }
-
- it = removed_items.begin();
- for( ; removed_items.end() != it; ++it)
- {
- // don't filter items right away
- removeItemByUUID(*it, false);
- }
-
- // Filter, rearrange and notify parent about shape changes
- filterItems();
-
- bool needs_refresh = add_limit_exceeded;
- setNeedsRefresh(needs_refresh);
- setForceRefresh(needs_refresh);
-
- // After list building completed, select items that had been requested to select before list was build
- if(!needs_refresh)
- {
- updateSelection();
- }
+ LL_RECORD_BLOCK_TIME(FTM_INVENTORY_ITEMS_REFRESH);
+
+ switch (mRefreshState)
+ {
+ case REFRESH_ALL:
+ {
+ mAddedItems.clear();
+ mRemovedItems.clear();
+ computeDifference(getIDs(), mAddedItems, mRemovedItems);
+ if (mRemovedItems.size() > 0)
+ {
+ mRefreshState = REFRESH_LIST_ERASE;
+ }
+ else if (mAddedItems.size() > 0)
+ {
+ mRefreshState = REFRESH_LIST_APPEND;
+ }
+ else
+ {
+ mRefreshState = REFRESH_LIST_SORT;
+ }
+
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ break;
+ }
+ case REFRESH_LIST_ERASE:
+ {
+ uuid_vec_t::const_iterator it = mRemovedItems.begin();
+ for (; mRemovedItems.end() != it; ++it)
+ {
+ // don't filter items right away
+ removeItemByUUID(*it, false);
+ }
+ mRemovedItems.clear();
+ mRefreshState = REFRESH_LIST_SORT; // fix visibility and arrange
+ break;
+ }
+ case REFRESH_LIST_APPEND:
+ {
+ static const unsigned ADD_LIMIT = 25; // Note: affects perfomance
+
+ unsigned int nadded = 0;
+
+ // form a list to add
+ uuid_vec_t::iterator it = mAddedItems.begin();
+ pairs_list_t panel_list;
+ while(mAddedItems.size() > 0 && nadded < ADD_LIMIT)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ llassert(item);
+ if (item)
+ {
+ LLPanel *list_item = createNewItem(item);
+ if (list_item)
+ {
+ item_pair_t* new_pair = new item_pair_t(list_item, item->getUUID());
+ panel_list.push_back(new_pair);
+ ++nadded;
+ }
+ }
+
+ it = mAddedItems.erase(it);
+ }
+
+ // add the list
+ // Note: usually item pairs are sorted with std::sort, but we are calling
+ // this function on idle and pairs' list can take a lot of time to sort
+ // through, so we are sorting items into list while adding them
+ addItemPairs(panel_list, false);
+
+ // update visibility of items in the list
+ std::string cur_filter = getFilterSubString();
+ LLStringUtil::toUpper(cur_filter);
+ LLSD action;
+ action.with("match_filter", cur_filter);
+
+ pairs_const_iterator_t pair_it = panel_list.begin();
+ for (; pair_it != panel_list.end(); ++pair_it)
+ {
+ item_pair_t* item_pair = *pair_it;
+ if (item_pair->first->getParent() != NULL)
+ {
+ updateItemVisibility(item_pair->first, action);
+ }
+ }
+
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+
+ if (mAddedItems.size() > 0)
+ {
+ mRefreshState = REFRESH_LIST_APPEND;
+ }
+ else
+ {
+ // Note: while we do sort and check visibility at REFRESH_LIST_APPEND, update
+ // could have changed something about existing items so redo checks for all items.
+ mRefreshState = REFRESH_LIST_SORT;
+ }
+ break;
+ }
+ case REFRESH_LIST_SORT:
+ {
+ // Filter, sort, rearrange and notify parent about shape changes
+ filterItems();
+
+ if (mAddedItems.size() == 0)
+ {
+ // After list building completed, select items that had been requested to select before list was build
+ updateSelection();
+ mRefreshState = REFRESH_COMPLETE;
+ }
+ else
+ {
+ mRefreshState = REFRESH_LIST_APPEND;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ setForceRefresh(mRefreshState != REFRESH_COMPLETE);
}
void LLInventoryItemsList::computeDifference(
@@ -204,24 +280,15 @@ void LLInventoryItemsList::computeDifference(
LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
}
-void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item, bool rearrange /*= true*/)
+LLPanel* LLInventoryItemsList::createNewItem(LLViewerInventoryItem* item)
{
- if (!item)
- {
- LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
- llassert(item != NULL);
- }
-
- LLPanelInventoryListItemBase *list_item = LLPanelInventoryListItemBase::create(item);
- if (!list_item)
- return;
-
- bool is_item_added = addItem(list_item, item->getUUID(), ADD_BOTTOM, rearrange);
- if (!is_item_added)
- {
- LL_WARNS() << "Couldn't add flat list item." << LL_ENDL;
- llassert(is_item_added);
- }
+ if (!item)
+ {
+ LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
+ llassert(item != NULL);
+ return NULL;
+ }
+ return LLPanelInventoryListItemBase::create(item);
}
// EOF
diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h
index 1aa230df99..fe05c2ed7c 100644
--- a/indra/newview/llinventoryitemslist.h
+++ b/indra/newview/llinventoryitemslist.h
@@ -51,9 +51,9 @@ public:
/**
* Let list know items need to be refreshed in next doIdle()
*/
- void setNeedsRefresh(bool needs_refresh){ mNeedsRefresh = needs_refresh; }
+ void setNeedsRefresh(bool needs_refresh){ mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; }
- bool getNeedsRefresh(){ return mNeedsRefresh; }
+ U32 getNeedsRefresh(){ return mRefreshState; }
/**
* Sets the flag indicating that the list needs to be refreshed even if it is
@@ -71,7 +71,7 @@ public:
* This is needed for example to filter items of the list hidden by closed
* accordion tab.
*/
- void doIdle(); // Real idle routine
+ virtual void doIdle(); // Real idle routine
static void idle(void* user_data); // static glue to doIdle()
protected:
@@ -94,17 +94,29 @@ protected:
void computeDifference(const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved);
/**
- * Add an item to the list
- */
- virtual void addNewItem(LLViewerInventoryItem* item, bool rearrange = true);
+ * Create panel(item) from inventory item
+ */
+ virtual LLPanel* createNewItem(LLViewerInventoryItem* item);
+
+protected:
+ enum ERefreshStates
+ {
+ REFRESH_COMPLETE = 0,
+ REFRESH_LIST_SORT,
+ REFRESH_LIST_APPEND,
+ REFRESH_LIST_ERASE,
+ REFRESH_ALL
+ };
+
+ ERefreshStates mRefreshState;
private:
uuid_vec_t mIDs; // IDs of items that were added in refreshList().
// Will be used in refresh() to determine added and removed ids
uuid_vec_t mSelectTheseIDs; // IDs that will be selected if list is not loaded till now
-
- bool mNeedsRefresh;
+ uuid_vec_t mAddedItems;
+ uuid_vec_t mRemovedItems;
bool mForceRefresh;
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 8b9941c0ca..d897449310 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -779,6 +779,10 @@ void LLPanelOutfitEdit::onVisibilityChanged(const LLSD &in_visible_chain)
{
update();
}
+ else
+ {
+ mWearableListManager->holdProgress(); //list population restarts with visibility
+ }
}
void LLPanelOutfitEdit::onAddWearableClicked(void)
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index f8981d0c51..ee2270c323 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -653,24 +653,16 @@ LLWearableItemsList::~LLWearableItemsList()
{}
// virtual
-void LLWearableItemsList::addNewItem(LLViewerInventoryItem* item, bool rearrange /*= true*/)
+LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item)
{
- if (!item)
- {
- LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
- llassert(item != NULL);
- }
-
- LLPanelWearableOutfitItem *list_item = LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
- if (!list_item)
- return;
+ if (!item)
+ {
+ LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL;
+ llassert(item != NULL);
+ return NULL;
+ }
- bool is_item_added = addItem(list_item, item->getUUID(), ADD_BOTTOM, rearrange);
- if (!is_item_added)
- {
- LL_WARNS() << "Couldn't add flat list item." << LL_ENDL;
- llassert(is_item_added);
- }
+ return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
}
void LLWearableItemsList::updateList(const LLUUID& category_id)
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 18a30f083b..63e3e9dbc9 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -453,7 +453,7 @@ public:
virtual ~LLWearableItemsList();
- /*virtual*/ void addNewItem(LLViewerInventoryItem* item, bool rearrange = true);
+ /*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item);
void updateList(const LLUUID& category_id);