From eb3716fab93556e8e16da7a8f1756af448ed6d70 Mon Sep 17 00:00:00 2001
From: Sergei Litovchuk <slitovchuk@productengine.com>
Date: Wed, 19 May 2010 17:55:58 +0300
Subject: [PATCH] EXT-7157 FIXED Implemented outfit items sorting in "My
 Outfits" tab. - Moved wearable item name comparator from llcofwearables to
 llwearableitemslist. - Added wearable item type comparator. - Added item type
 and description getters to wearable item base class
 LLPanelInventoryListItemBase.

Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/407/

--HG--
branch : product-engine
---
 indra/llui/llflatlistview.cpp         |  2 +-
 indra/newview/llcofwearables.cpp      | 12 ----
 indra/newview/llcofwearables.h        | 57 ++---------------
 indra/newview/llinventoryitemslist.h  |  9 +++
 indra/newview/llwearableitemslist.cpp | 82 +++++++++++++++++++++++-
 indra/newview/llwearableitemslist.h   | 92 +++++++++++++++++++++++++++
 6 files changed, 190 insertions(+), 64 deletions(-)

diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 6bd16c9ee64..2433c14315f 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -1285,7 +1285,7 @@ void LLFlatListViewEx::filterItems()
 		}
 	}
 
-	rearrangeItems();
+	sort();
 	notifyParentItemsRectChanged();
 }
 
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 8d4430a9ea7..7c4ceb34583 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -49,18 +49,6 @@ const LLSD REARRANGE = LLSD().with("rearrange", LLSD());
 static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR;
 
 
-bool LLWearableItemNameComparator::doCompare(const LLPanelWearableListItem* wearable_item1, const LLPanelWearableListItem* wearable_item2) const
-{
-	std::string name1 = wearable_item1->getItemName();
-	std::string name2 = wearable_item2->getItemName();
-
-	LLStringUtil::toUpper(name1);
-	LLStringUtil::toUpper(name2);
-
-	return name1 < name2;
-}
-
-
 LLCOFWearables::LLCOFWearables() : LLPanel(),
 	mAttachments(NULL),
 	mClothing(NULL),
diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h
index 612bb103d21..583ee962477 100644
--- a/indra/newview/llcofwearables.h
+++ b/indra/newview/llcofwearables.h
@@ -33,59 +33,16 @@
 #ifndef LL_LLCOFWEARABLES_H
 #define LL_LLCOFWEARABLES_H
 
+// llui
+#include "llflatlistview.h"
 #include "llpanel.h"
-#include "llinventorymodel.h"
-#include "llappearancemgr.h"
-#include "llwearableitemslist.h"
-
-class LLFlatListView;
-
-
-/** Abstract comparator of wearable list items */
-class LLWearableListItemComparator : public LLFlatListView::ItemComparator
-{
-	LOG_CLASS(LLWearableListItemComparator);
-
-public:
-	LLWearableListItemComparator() {};
-	virtual ~LLWearableListItemComparator() {};
-
-	virtual bool compare(const LLPanel* item1, const LLPanel* item2) const
-	{
-		const LLPanelWearableListItem* wearable_item1 = dynamic_cast<const LLPanelWearableListItem*>(item1);
-		const LLPanelWearableListItem* wearable_item2 = dynamic_cast<const LLPanelWearableListItem*>(item2);
-
-		if (!wearable_item1 || !wearable_item2)
-		{
-			llwarning("item1 and item2 cannot be null", 0);
-			return true;
-		}
-
-		return doCompare(wearable_item1, wearable_item2);
-	}
 
-protected:
-
-	/** 
-	 * Returns true if wearable_item1 < wearable_item2, false otherwise 
-	 * Implement this method in your particular comparator.
-	 */
-	virtual bool doCompare(const LLPanelWearableListItem* wearable_item1, const LLPanelWearableListItem* wearable_item2) const = 0;
-};
-
-
-class LLWearableItemNameComparator : public LLWearableListItemComparator
-{
-	LOG_CLASS(LLWearableItemNameComparator);
-
-public:
-	LLWearableItemNameComparator() {};
-	virtual ~LLWearableItemNameComparator() {};
-
-protected:
-	virtual bool doCompare(const LLPanelWearableListItem* wearable_item1, const LLPanelWearableListItem* wearable_item2) const;
-};
+#include "llappearancemgr.h"
+#include "llinventorymodel.h"
 
+class LLPanelClothingListItem;
+class LLPanelBodyPartsListItem;
+class LLPanelDeletableWearableListItem;
 
 /**
  * Adaptor between LLAccordionCtrlTab and LLFlatListView to facilitate communication between them 
diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h
index a3863b511cb..807952948b9 100644
--- a/indra/newview/llinventoryitemslist.h
+++ b/indra/newview/llinventoryitemslist.h
@@ -124,6 +124,15 @@ class LLPanelInventoryListItemBase : public LLPanel
 	/** Get the name of a corresponding inventory item */
 	const std::string& getItemName() const { return mItem->getName(); }
 
+	/** Get the asset type of a corresponding inventory item */
+	LLAssetType::EType getType() const { return mItem->getType(); }
+
+	/** Get the wearable type of a corresponding inventory item */
+	LLWearableType::EType getWearableType() const { return mItem->getWearableType(); }
+
+	/** Get the description of a corresponding inventory item */
+	const std::string& getDescription() const { return mItem->getDescription(); }
+
 	virtual ~LLPanelInventoryListItemBase(){}
 
 protected:
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index bac66d966a0..b209dfecce7 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -296,6 +296,84 @@ std::string LLPanelDummyClothingListItem::wearableTypeToString(LLWearableType::E
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
+/*virtual*/
+bool LLWearableItemNameComparator::doCompare(const LLPanelInventoryListItemBase* wearable_item1, const LLPanelInventoryListItemBase* wearable_item2) const
+{
+	std::string name1 = wearable_item1->getItemName();
+	std::string name2 = wearable_item2->getItemName();
+
+	LLStringUtil::toUpper(name1);
+	LLStringUtil::toUpper(name2);
+
+	return name1 < name2;
+}
+
+/*virtual*/
+bool LLWearableItemTypeNameComparator::doCompare(const LLPanelInventoryListItemBase* wearable_item1, const LLPanelInventoryListItemBase* wearable_item2) const
+{
+	const LLAssetType::EType item_type1 = wearable_item1->getType();
+	const LLAssetType::EType item_type2 = wearable_item2->getType();
+
+	LLWearableItemTypeNameComparator::ETypeListOrder item_type_order1 = getTypeListOrder(item_type1);
+	LLWearableItemTypeNameComparator::ETypeListOrder item_type_order2 = getTypeListOrder(item_type2);
+
+	if (item_type_order1 != item_type_order2)
+	{
+		// If items are of different asset types we can compare them
+		// by types order in the list.
+		return item_type_order1 < item_type_order2;
+	}
+
+	if (item_type_order1 & TLO_NOT_CLOTHING)
+	{
+		// If both items are of the same asset type except AT_CLOTHING
+		// we can compare them by name.
+		return LLWearableItemNameComparator::doCompare(wearable_item1, wearable_item2);
+	}
+
+	const LLWearableType::EType item_wearable_type1 = wearable_item1->getWearableType();
+	const LLWearableType::EType item_wearable_type2 = wearable_item2->getWearableType();
+
+	if (item_wearable_type1 != item_wearable_type2)
+	{
+		// If items are of different clothing types they are compared
+		// by clothing types order determined in LLWearableType::EType.
+		return item_wearable_type1 < item_wearable_type2;
+	}
+	else
+	{
+		// If both items are of the same clothing type they are compared
+		// by description and place in reverse order i.e. outer layer item
+		// on top.
+		return wearable_item1->getDescription() > wearable_item2->getDescription();
+	}
+}
+
+// static
+LLWearableItemTypeNameComparator::ETypeListOrder LLWearableItemTypeNameComparator::getTypeListOrder(LLAssetType::EType item_type)
+{
+	switch (item_type)
+	{
+	case LLAssetType::AT_OBJECT:
+		return TLO_ATTACHMENT;
+
+	case LLAssetType::AT_CLOTHING:
+		return TLO_CLOTHING;
+
+	case LLAssetType::AT_BODYPART:
+		return TLO_BODYPART;
+
+	default:
+		return TLO_UNKNOWN;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+static const LLWearableItemTypeNameComparator WEARABLE_TYPE_NAME_COMPARATOR;
+
 static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list");
 
 LLWearableItemsList::Params::Params()
@@ -303,7 +381,9 @@ LLWearableItemsList::Params::Params()
 
 LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)
 :	LLInventoryItemsList(p)
-{}
+{
+	setComparator(&WEARABLE_TYPE_NAME_COMPARATOR);
+}
 
 // virtual
 LLWearableItemsList::~LLWearableItemsList()
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 5e3202c6876..2cab5a07a2b 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -171,6 +171,98 @@ class LLPanelDummyClothingListItem : public LLPanelWearableListItem
 	LLWearableType::EType mWearableType;
 };
 
+/**
+ * @class LLWearableListItemComparator
+ *
+ * Abstract comparator of wearable list items.
+ */
+class LLWearableListItemComparator : public LLFlatListView::ItemComparator
+{
+	LOG_CLASS(LLWearableListItemComparator);
+
+public:
+	LLWearableListItemComparator() {};
+	virtual ~LLWearableListItemComparator() {};
+
+	virtual bool compare(const LLPanel* item1, const LLPanel* item2) const
+	{
+		const LLPanelInventoryListItemBase* wearable_item1 = dynamic_cast<const LLPanelInventoryListItemBase*>(item1);
+		const LLPanelInventoryListItemBase* wearable_item2 = dynamic_cast<const LLPanelInventoryListItemBase*>(item2);
+
+		if (!wearable_item1 || !wearable_item2)
+		{
+			llwarning("item1 and item2 cannot be null", 0);
+			return true;
+		}
+
+		return doCompare(wearable_item1, wearable_item2);
+	}
+
+protected:
+
+	/**
+	 * Returns true if wearable_item1 < wearable_item2, false otherwise
+	 * Implement this method in your particular comparator.
+	 */
+	virtual bool doCompare(const LLPanelInventoryListItemBase* wearable_item1, const LLPanelInventoryListItemBase* wearable_item2) const = 0;
+};
+
+/**
+ * @class LLWearableItemNameComparator
+ *
+ * Comparator for sorting wearable list items by name.
+ */
+class LLWearableItemNameComparator : public LLWearableListItemComparator
+{
+	LOG_CLASS(LLWearableItemNameComparator);
+
+public:
+	LLWearableItemNameComparator() {};
+	virtual ~LLWearableItemNameComparator() {};
+
+protected:
+	/*virtual*/ bool doCompare(const LLPanelInventoryListItemBase* wearable_item1, const LLPanelInventoryListItemBase* wearable_item2) const;
+};
+
+/**
+ * @class LLWearableItemTypeNameComparator
+ *
+ * Comparator for sorting wearable list items by type and name.
+ */
+class LLWearableItemTypeNameComparator : public LLWearableItemNameComparator
+{
+	LOG_CLASS(LLWearableItemTypeNameComparator);
+
+public:
+	LLWearableItemTypeNameComparator() {};
+	virtual ~LLWearableItemTypeNameComparator() {};
+
+protected:
+	/**
+	 * Returns "true" if wearable_item1 is placed before wearable_item2 sorted by the following:
+	 *   - Attachments (abc order)
+	 *   - Clothing
+	 *         - by type (types order determined in LLWearableType::EType)
+	 *         - outer layer on top
+	 *   - Body Parts (abc order),
+	 * "false" otherwise.
+	 */
+	/*virtual*/ bool doCompare(const LLPanelInventoryListItemBase* wearable_item1, const LLPanelInventoryListItemBase* wearable_item2) const;
+
+private:
+	enum ETypeListOrder
+	{
+		TLO_ATTACHMENT	= 0x01,
+		TLO_CLOTHING	= 0x02,
+		TLO_BODYPART	= 0x04,
+		TLO_UNKNOWN		= 0x08,
+
+		TLO_NOT_CLOTHING = TLO_ATTACHMENT | TLO_BODYPART | TLO_UNKNOWN
+	};
+
+	static LLWearableItemTypeNameComparator::ETypeListOrder getTypeListOrder(LLAssetType::EType item_type);
+};
+
 /**
  * @class LLWearableItemsList
  *
-- 
GitLab