From b15e2beabfc2987ba8d17b74014074ba313b5db7 Mon Sep 17 00:00:00 2001
From: Dmitry Zaporozhan <dzaporozhan@productengine.com>
Date: Thu, 22 Apr 2010 15:48:48 +0300
Subject: [PATCH] Implemented EXT-6724(normal task) - Implement flat list view
 of filtered inventory for "add wearables" panel of outfit editor 1. Modified
 LLInventoryItemsList - implemented delayed item construction. Items are added
 during draw, not more than 50 items will be added in single draw. This lets
 us reduce system overload during multiple panel construction. 2. Implemented
 LLFilteredWearableListManager to populate inventory flat list with data. This
 class filters entire inventory according to specified filter and populates
 specified inventory list with data. 3. Created
 LLCommonUtil::computeDifference() to avoid code copy-pasting(will use it in
 all appropriate places in next review request)

Reviewed by Mike Antipov - https://codereview.productengine.com/secondlife/r/301/

--HG--
branch : product-engine
---
 indra/llcommon/CMakeLists.txt                 |   2 +
 indra/llcommon/llcommonutils.cpp              |  61 ++++++++++
 indra/llcommon/llcommonutils.h                |  51 ++++++++
 indra/newview/CMakeLists.txt                  |   2 +
 indra/newview/llfilteredwearablelist.cpp      | 113 ++++++++++++++++++
 indra/newview/llfilteredwearablelist.h        |  70 +++++++++++
 indra/newview/llinventoryitemslist.cpp        |  96 +++++++++++++--
 indra/newview/llinventoryitemslist.h          |  34 ++++++
 indra/newview/llpaneloutfitedit.cpp           |  14 ++-
 indra/newview/llpaneloutfitedit.h             |   6 +-
 .../default/xui/en/panel_outfit_edit.xml      |  24 ++++
 11 files changed, 458 insertions(+), 15 deletions(-)
 create mode 100644 indra/llcommon/llcommonutils.cpp
 create mode 100644 indra/llcommon/llcommonutils.h
 create mode 100644 indra/newview/llfilteredwearablelist.cpp
 create mode 100644 indra/newview/llfilteredwearablelist.h

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 4481d334b27..3c689930b8b 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -35,6 +35,7 @@ set(llcommon_SOURCE_FILES
     llbase32.cpp
     llbase64.cpp
     llcommon.cpp
+    llcommonutils.cpp
     llcoros.cpp
     llcrc.cpp
     llcriticaldamp.cpp
@@ -124,6 +125,7 @@ set(llcommon_HEADER_FILES
     llchat.h
     llclickaction.h
     llcommon.h
+    llcommonutils.h
     llcoros.h
     llcrc.h
     llcriticaldamp.h
diff --git a/indra/llcommon/llcommonutils.cpp b/indra/llcommon/llcommonutils.cpp
new file mode 100644
index 00000000000..0022dc69159
--- /dev/null
+++ b/indra/llcommon/llcommonutils.cpp
@@ -0,0 +1,61 @@
+/**
+ * @file llcommonutils.h
+ * @brief Commin utils
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llcommonutils.h"
+
+void LLCommonUtils::computeDifference(
+	const uuid_vec_t& vnew,
+	const uuid_vec_t& vcur,
+	uuid_vec_t& vadded,
+	uuid_vec_t& vremoved)
+{
+	uuid_vec_t vnew_copy(vnew);
+	uuid_vec_t vcur_copy(vcur);
+
+	std::sort(vnew_copy.begin(), vnew_copy.end());
+	std::sort(vcur_copy.begin(), vcur_copy.end());
+
+	size_t maxsize = llmax(vnew_copy.size(), vcur_copy.size());
+	vadded.resize(maxsize);
+	vremoved.resize(maxsize);
+
+	uuid_vec_t::iterator it;
+	// what was removed
+	it = set_difference(vcur_copy.begin(), vcur_copy.end(), vnew_copy.begin(), vnew_copy.end(), vremoved.begin());
+	vremoved.erase(it, vremoved.end());
+
+	// what was added
+	it = set_difference(vnew_copy.begin(), vnew_copy.end(), vcur_copy.begin(), vcur_copy.end(), vadded.begin());
+	vadded.erase(it, vadded.end());
+}
+
+// EOF
diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h
new file mode 100644
index 00000000000..f769ab87d36
--- /dev/null
+++ b/indra/llcommon/llcommonutils.h
@@ -0,0 +1,51 @@
+/**
+ * @file llcommonutils.h
+ * @brief Common utils
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCOMMONUTILS_H
+#define LL_LLCOMMONUTILS_H
+
+namespace LLCommonUtils
+{
+	/**
+	 * Computes difference between 'vnew' and 'vcur' vectors.
+	 * Items present in 'vnew' and missing in 'vcur' are treated as added and are copied into 'vadded'
+	 * Items missing in 'vnew' and present in 'vcur' are treated as removed and are copied into 'vremoved'
+	 */
+	LL_COMMON_API void computeDifference(
+		const uuid_vec_t& vnew,
+		const uuid_vec_t& vcur,
+		uuid_vec_t& vadded,
+		uuid_vec_t& vremoved);
+};
+
+#endif //LL_LLCOMMONUTILS_H
+
+// EOF
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c372edbea1b..bfb5798909b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -142,6 +142,7 @@ set(viewer_SOURCE_FILES
     llfavoritesbar.cpp
     llfeaturemanager.cpp
     llfilepicker.cpp
+    llfilteredwearablelist.cpp
     llfirstuse.cpp
     llflexibleobject.cpp
     llfloaterabout.cpp
@@ -651,6 +652,7 @@ set(viewer_HEADER_FILES
     llfavoritesbar.h
     llfeaturemanager.h
     llfilepicker.h
+    llfilteredwearablelist.h
     llfirstuse.h
     llflexibleobject.h
     llfloaterabout.h
diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp
new file mode 100644
index 00000000000..01d3c3f22e2
--- /dev/null
+++ b/indra/newview/llfilteredwearablelist.cpp
@@ -0,0 +1,113 @@
+/**
+ * @file llfilteredwearablelist.cpp
+ * @brief Functionality for showing filtered wearable flat list
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfilteredwearablelist.h"
+
+// newview
+#include "llinventoryfunctions.h"
+#include "llinventoryitemslist.h"
+#include "llinventorymodel.h"
+
+class LLFindItemsByMask : public LLInventoryCollectFunctor
+{
+public:
+	LLFindItemsByMask(U64 mask)
+		: mFilterMask(mask)
+	{}
+
+	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+	{
+		if(item)
+		{
+			if( mFilterMask & (1LL << item->getInventoryType()) )
+			{
+				return TRUE;
+			}
+		}
+		return FALSE;
+	}
+
+private:
+	U64 mFilterMask;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask)
+: mWearableList(list)
+, mFilterMask(filter_mask)
+{
+	llassert(mWearableList);
+	gInventory.addObserver(this);
+	gInventory.fetchDescendentsOf(gInventory.getRootFolderID());
+}
+
+LLFilteredWearableListManager::~LLFilteredWearableListManager()
+{
+	gInventory.removeObserver(this);
+}
+
+void LLFilteredWearableListManager::changed(U32 mask)
+{
+	if(!gInventory.isInventoryUsable())
+	{
+		return;
+	}
+
+	populateList();
+}
+
+void LLFilteredWearableListManager::setFilterMask(U64 mask)
+{
+	mFilterMask = mask;
+	populateList();
+}
+
+void LLFilteredWearableListManager::populateList()
+{
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t item_array;
+	LLFindItemsByMask collector(mFilterMask);
+
+	gInventory.collectDescendentsIf(
+		gInventory.getRootFolderID(),
+		cat_array,
+		item_array,
+		LLInventoryModel::EXCLUDE_TRASH,
+		collector);
+
+	// Probably will also need to get items from Library (waiting for reply in EXT-6724).
+
+	mWearableList->refreshList(item_array);
+}
+
+// EOF
diff --git a/indra/newview/llfilteredwearablelist.h b/indra/newview/llfilteredwearablelist.h
new file mode 100644
index 00000000000..3f42833bb47
--- /dev/null
+++ b/indra/newview/llfilteredwearablelist.h
@@ -0,0 +1,70 @@
+/**
+ * @file llfilteredwearablelist.h
+ * @brief Functionality for showing filtered wearable flat list
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFILTEREDWEARABLELIST_H
+#define LL_LLFILTEREDWEARABLELIST_H
+
+#include "llinventoryobserver.h"
+
+class LLInventoryItemsList;
+
+// Class that fills LLInventoryItemsList with filtered data.
+class LLFilteredWearableListManager : public LLInventoryObserver
+{
+	LOG_CLASS(LLFilteredWearableListManager);
+public:
+
+	LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask);
+	~LLFilteredWearableListManager();
+
+	/** LLInventoryObserver implementation
+	 *
+	 */
+	/*virtual*/ void changed(U32 mask);
+
+	/**
+	 * Sets new filter and applies it immediately
+	 */
+	void setFilterMask(U64 mask);
+
+	/**
+	 * Populates wearable list with filtered data.
+	 */
+	void populateList();
+
+private:
+	LLInventoryItemsList* mWearableList;
+	U64 mFilterMask;
+};
+
+#endif //LL_LLFILTEREDWEARABLELIST_H
+
+// EOF
diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp
index 9489e0f2e41..9f54b86607e 100644
--- a/indra/newview/llinventoryitemslist.cpp
+++ b/indra/newview/llinventoryitemslist.cpp
@@ -33,6 +33,9 @@
 
 #include "llinventoryitemslist.h"
 
+// llcommon
+#include "llcommonutils.h"
+
 #include "lliconctrl.h"
 
 #include "llinventoryfunctions.h"
@@ -112,6 +115,7 @@ void LLPanelInventoryItem::onMouseLeave(S32 x, S32 y, MASK mask)
 
 LLInventoryItemsList::LLInventoryItemsList(const LLFlatListView::Params& p)
 :	LLFlatListView(p)
+,	mNeedsRefresh(false)
 {}
 
 // virtual
@@ -120,22 +124,88 @@ LLInventoryItemsList::~LLInventoryItemsList()
 
 void LLInventoryItemsList::refreshList(const LLInventoryModel::item_array_t item_array)
 {
-	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;
+}
 
-	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
-		 iter != item_array.end();
-		 iter++)
+void LLInventoryItemsList::draw()
+{
+	LLFlatListView::draw();
+	if(mNeedsRefresh)
 	{
-		LLViewerInventoryItem *item = (*iter);
-
-		LLPanelInventoryItem *list_item = new LLPanelInventoryItem(item->getType(),
-																   item->getInventoryType(),
-																   item->getFlags(),
-																   item->getName(),
-																   LLStringUtil::null);
-		if (!addItem(list_item, item->getUUID()))
+		refresh();
+	}
+}
+
+void LLInventoryItemsList::refresh()
+{
+	static const unsigned ADD_LIMIT = 50;
+
+	uuid_vec_t added_items;
+	uuid_vec_t removed_items;
+
+	computeDifference(getIDs(), added_items, removed_items);
+
+	bool add_limit_exceeded = false;
+	unsigned nadded = 0;
+
+	uuid_vec_t::const_iterator it = added_items.begin();
+	for( ; added_items.end() != it; ++it)
+	{
+		if(nadded >= ADD_LIMIT)
 		{
-			llerrs << "Couldn't add flat item." << llendl;
+			add_limit_exceeded = true;
+			break;
 		}
+		LLViewerInventoryItem* item = gInventory.getItem(*it);
+		addNewItem(item);
+		++nadded;
+	}
+
+	it = removed_items.begin();
+	for( ; removed_items.end() != it; ++it)
+	{
+		removeItemByUUID(*it);
 	}
+
+	bool needs_refresh = add_limit_exceeded;
+	setNeedsRefresh(needs_refresh);
+}
+
+void LLInventoryItemsList::computeDifference(
+	const uuid_vec_t& vnew,
+	uuid_vec_t& vadded,
+	uuid_vec_t& vremoved)
+{
+	uuid_vec_t vcur;
+	{
+		std::vector<LLSD> vcur_values;
+		getValues(vcur_values);
+
+		for (size_t i=0; i<vcur_values.size(); i++)
+			vcur.push_back(vcur_values[i].asUUID());
+	}
+
+	LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
 }
+
+void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item)
+{
+	llassert(item);
+
+	LLPanelInventoryItem *list_item = new LLPanelInventoryItem(item->getType(),
+		item->getInventoryType(), item->getFlags(), item->getName(), LLStringUtil::null);
+
+	if (!addItem(list_item, item->getUUID()))
+	{
+		llwarns << "Couldn't add flat list item." << llendl;
+		llassert(!"Couldn't add flat list item.");
+	}
+}
+
+// EOF
diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h
index bba739dbbfc..0ca4146867f 100644
--- a/indra/newview/llinventoryitemslist.h
+++ b/indra/newview/llinventoryitemslist.h
@@ -80,9 +80,43 @@ class LLInventoryItemsList : public LLFlatListView
 
 	void refreshList(const LLInventoryModel::item_array_t item_array);
 
+	/**
+	 * Let list know items need to be refreshed in next draw()
+	 */
+	void setNeedsRefresh(bool needs_refresh){ mNeedsRefresh = needs_refresh; }
+
+	bool getNeedsRefresh(){ return mNeedsRefresh; }
+
+	/*virtual*/ void draw();
+
 protected:
 	friend class LLUICtrlFactory;
 	LLInventoryItemsList(const LLFlatListView::Params& p);
+
+	uuid_vec_t& getIDs() { return mIDs; }
+
+	/**
+	 * Refreshes list items, adds new items and removes deleted items. 
+	 * Called from draw() until all new items are added, ,
+	 * maximum 50 items can be added during single call.
+	 */
+	void refresh();
+
+	/**
+	 * Compute difference between new items and current items, fills 'vadded' with added items,
+	 * 'vremoved' with removed items. See LLCommonUtils::computeDifference
+	 */
+	void computeDifference(const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+
+	/**
+	 * Add an item to the list
+	 */
+	void addNewItem(LLViewerInventoryItem* item);
+
+private:
+	uuid_vec_t mIDs; // IDs of items that were added in refreshList().
+					 // Will be used in refresh() to determine added and removed ids
+	bool mNeedsRefresh;
 };
 
 #endif //LL_LLINVENTORYITEMSLIST_H
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index ce17e1d6245..e139cb31d65 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -38,7 +38,9 @@
 #include "llagent.h"
 #include "llagentwearables.h"
 #include "llappearancemgr.h"
+#include "llfilteredwearablelist.h"
 #include "llinventory.h"
+#include "llinventoryitemslist.h"
 #include "llviewercontrol.h"
 #include "llui.h"
 #include "llfloater.h"
@@ -164,6 +166,7 @@ BOOL LLPanelOutfitEdit::postBuild()
 
 	childSetCommitCallback("add_btn", boost::bind(&LLPanelOutfitEdit::showAddWearablesPanel, this), NULL);
 	childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);
+	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredWearablesPanel, this), NULL);
 
 	mLookContents = getChild<LLScrollListCtrl>("look_items_list");
 	mLookContents->sortByColumn("look_item_sort", TRUE);
@@ -229,6 +232,9 @@ BOOL LLPanelOutfitEdit::postBuild()
 	save_registar.add("Outfit.SaveAsNew.Action", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true));
 	mSaveMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_save_outfit.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 
+	mWearableListManager = new LLFilteredWearableListManager(
+		getChild<LLInventoryItemsList>("filtered_wearables_list"), ALL_ITEMS_MASK);
+
 	return TRUE;
 }
 
@@ -242,6 +248,11 @@ void LLPanelOutfitEdit::showWearablesFilter()
 	childSetVisible("filter_combobox_panel", childGetValue("filter_button"));
 }
 
+void LLPanelOutfitEdit::showFilteredWearablesPanel()
+{
+	childSetVisible("filtered_wearables_panel", !childIsVisible("filtered_wearables_panel"));
+}
+
 void LLPanelOutfitEdit::saveOutfit(bool as_new)
 {
 	if (!as_new && LLAppearanceMgr::getInstance()->updateBaseOutfit())
@@ -275,6 +286,7 @@ void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl)
 	{
 		U32 curr_filter_type = type_filter->getCurrentIndex();
 		mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask);
+		mWearableListManager->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask);
 	}
 	
 	mSavedFolderState->setApply(TRUE);
@@ -577,4 +589,4 @@ void LLPanelOutfitEdit::displayCurrentOutfit()
 	updateLookInfo();
 }
 
-
+// EOF
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 69e80165344..308ee23115c 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -55,6 +55,7 @@ class LLScrollListCtrl;
 class LLToggleableMenu;
 class LLLookFetchObserver;
 class LLFilterEditor;
+class LLFilteredWearableListManager;
 
 class LLPanelOutfitEdit : public LLPanel
 {
@@ -88,6 +89,7 @@ class LLPanelOutfitEdit : public LLPanel
 
 	void showAddWearablesPanel();
 	void showWearablesFilter();
+	void showFilteredWearablesPanel();
 	void saveOutfit(bool as_new = false);
 	void showSaveMenu();
 
@@ -122,7 +124,9 @@ class LLPanelOutfitEdit : public LLPanel
 	LLButton*			mUpBtn;
 	LLButton*			mEditWearableBtn;
 	LLToggleableMenu*	mSaveMenu;
-	
+
+	LLFilteredWearableListManager* mWearableListManager;
+
 	LLLookFetchObserver*		mFetchLook;
 	LLInventoryLookObserver*	mLookObserver;
 	std::vector<LLLookItemType> mLookItemTypes;
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index c77e4e8d5e2..b1f0ff15cb0 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -341,6 +341,30 @@
              top_pad="5"
              width="300"/>
 
+            <panel
+             name="filtered_wearables_panel"
+             background_opaque="true"
+             background_visible="true"
+             layout="topleft"
+             follows="left|top|right|bottom"
+             border="false"
+             height="155"
+             left="0"
+             mouse_opaque="false"
+             width="300"
+             top_delta="0"
+             visible="false">
+             <wearable_items_list
+              name="filtered_wearables_list"
+              allow_select="true"
+              layout="topleft"
+              follows="all"
+              width="300"
+              height="155"
+              left="0"
+              top="0" />
+            </panel>
+
             <panel
              background_visible="true"
              bevel_style="none"
-- 
GitLab