From d42fd6cf7fa3ac4d7e2ef35cef50eb7740b4ec6d Mon Sep 17 00:00:00 2001
From: Paul Guslisty <pguslisty@productengine.com>
Date: Fri, 28 May 2010 20:10:10 +0300
Subject: EXT-7472 FIXED Open add to outfit panel by (+) button click on
 unwearable items and by selecting 'Replace' menu item click body part context
 menu

Main changes:
- Added callback for a '(+) button' to the LLCOFCallbacks and bind it with LLPanelOutfitEdit::onAddWearableClicked
- Created the callback(LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked) for 'Replace' menu item of context menu

Related changes:
- Changed LLFilteredWearableListManager so that it can use different functors (subclasses of LLInventoryCollectFunctor) as a criterion for LLInventoryItemsList filtering. Before it used only LLFindNonLinksByMask filter. Moved LLFindNonLinksByMask from to the llfilteredwearablelist.cpp to the llinventoryfunctions.h
- Created getter 'LLPanelDummyClothingListItem::getWearableType()' for LLPanelDummyClothingListItem
- Made 'add wearables panel' a member of LLPanelOutfitEdit so that not to use findChild each time panel is needed

Reviewed by Igor Borovkov at http://jira.secondlife.com/browse/EXT-7472

--HG--
branch : product-engine
---
 indra/newview/llcofwearables.cpp         | 16 +++++++++--
 indra/newview/llcofwearables.h           |  3 ++
 indra/newview/llfilteredwearablelist.cpp | 46 +++++++++---------------------
 indra/newview/llfilteredwearablelist.h   |  9 +++---
 indra/newview/llinventoryfunctions.cpp   |  5 ++++
 indra/newview/llinventoryfunctions.h     | 35 ++++++++++++++++++++++-
 indra/newview/llpaneloutfitedit.cpp      | 49 +++++++++++++++++++++++++++++---
 indra/newview/llpaneloutfitedit.h        |  9 ++++++
 indra/newview/llwearableitemslist.cpp    |  5 ++++
 indra/newview/llwearableitemslist.h      |  1 +
 10 files changed, 134 insertions(+), 44 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index dfc203111a..6e7a7fe937 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -43,6 +43,8 @@
 #include "llmenugl.h"
 #include "llviewermenu.h"
 #include "llwearableitemslist.h"
+#include "llpaneloutfitedit.h"
+#include "llsidetray.h"
 
 static LLRegisterPanelClassWrapper<LLCOFAccordionListAdaptor> t_cof_accodion_list_adaptor("accordion_list_adaptor");
 
@@ -135,8 +137,10 @@ protected:
 		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
 		LLUUID selected_id = mUUIDs.back();
 
-		registrar.add("BodyPart.Replace", boost::bind(&LLAppearanceMgr::wearItemOnAvatar,
-			LLAppearanceMgr::getInstance(), selected_id, true, true));
+		// *HACK* need to pass pointer to LLPanelOutfitEdit instead of LLSideTray::getInstance()->getPanel().
+		// LLSideTray::getInstance()->getPanel() is rather slow variant
+		LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit"));
+		registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id));
 		registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
 
 		enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2));
@@ -416,6 +420,7 @@ void LLCOFWearables::addClothingTypesDummies(const LLAppearanceMgr::wearables_by
 		LLWearableType::EType w_type = static_cast<LLWearableType::EType>(type);
 		LLPanelInventoryListItemBase* item_panel = LLPanelDummyClothingListItem::create(w_type);
 		if(!item_panel) continue;
+		item_panel->childSetAction("btn_add", mCOFCallbacks.mAddWearable);
 		mClothing->addItem(item_panel, LLUUID::null, ADD_BOTTOM, false);
 	}
 }
@@ -435,6 +440,13 @@ bool LLCOFWearables::getSelectedUUIDs(uuid_vec_t& selected_ids)
 	return selected_ids.size() != 0;
 }
 
+LLPanel* LLCOFWearables::getSelectedItem()
+{
+	if (!mLastSelectedList) return NULL;
+
+	return mLastSelectedList->getSelectedItem();
+}
+
 void LLCOFWearables::clear()
 {
 	mAttachments->clear();
diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h
index 590aa709dd..8f8bda2be8 100644
--- a/indra/newview/llcofwearables.h
+++ b/indra/newview/llcofwearables.h
@@ -107,6 +107,7 @@ public:
 		
 		typedef boost::function<void (void*)> cof_callback_t;
 
+		cof_callback_t mAddWearable;
 		cof_callback_t mMoveWearableCloser;
 		cof_callback_t mMoveWearableFurther;
 		cof_callback_t mEditWearable;
@@ -123,6 +124,8 @@ public:
 	LLUUID getSelectedUUID();
 	bool getSelectedUUIDs(uuid_vec_t& selected_ids);
 
+	LLPanel* getSelectedItem();
+
 	void refresh();
 	void clear();
 
diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp
index fd99f673e0..28e159421c 100644
--- a/indra/newview/llfilteredwearablelist.cpp
+++ b/indra/newview/llfilteredwearablelist.cpp
@@ -37,32 +37,10 @@
 #include "llinventoryitemslist.h"
 #include "llinventorymodel.h"
 
-class LLFindNonLinksByMask : public LLInventoryCollectFunctor
-{
-public:
-	LLFindNonLinksByMask(U64 mask)
-		: mFilterMask(mask)
-	{}
-
-	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
-	{
-		if(item && !item->getIsLinkType() && (mFilterMask & (1LL << item->getInventoryType())) )
-		{
-			return true;
-		}
-
-		return false;
-	}
 
-private:
-	U64 mFilterMask;
-};
-
-//////////////////////////////////////////////////////////////////////////
-
-LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask)
+LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector)
 : mWearableList(list)
-, mFilterMask(filter_mask)
+, mCollector(collector)
 {
 	llassert(mWearableList);
 	gInventory.addObserver(this);
@@ -84,9 +62,9 @@ void LLFilteredWearableListManager::changed(U32 mask)
 	populateList();
 }
 
-void LLFilteredWearableListManager::setFilterMask(U64 mask)
+void LLFilteredWearableListManager::setFilterCollector(LLInventoryCollectFunctor* collector)
 {
-	mFilterMask = mask;
+	mCollector = collector;
 	populateList();
 }
 
@@ -94,14 +72,16 @@ void LLFilteredWearableListManager::populateList()
 {
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t item_array;
-	LLFindNonLinksByMask collector(mFilterMask);
 
-	gInventory.collectDescendentsIf(
-		gInventory.getRootFolderID(),
-		cat_array,
-		item_array,
-		LLInventoryModel::EXCLUDE_TRASH,
-		collector);
+	if(mCollector)
+	{
+		gInventory.collectDescendentsIf(
+				gInventory.getRootFolderID(),
+				cat_array,
+				item_array,
+				LLInventoryModel::EXCLUDE_TRASH,
+				*mCollector);
+	}
 
 	// Probably will also need to get items from Library (waiting for reply in EXT-6724).
 
diff --git a/indra/newview/llfilteredwearablelist.h b/indra/newview/llfilteredwearablelist.h
index 0780c02442..b7825c07af 100644
--- a/indra/newview/llfilteredwearablelist.h
+++ b/indra/newview/llfilteredwearablelist.h
@@ -32,6 +32,7 @@
 #ifndef LL_LLFILTEREDWEARABLELIST_H
 #define LL_LLFILTEREDWEARABLELIST_H
 
+#include "llinventoryfunctions.h"
 #include "llinventoryobserver.h"
 
 class LLInventoryItemsList;
@@ -42,7 +43,7 @@ class LLFilteredWearableListManager : public LLInventoryObserver
 	LOG_CLASS(LLFilteredWearableListManager);
 public:
 
-	LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask);
+	LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector);
 	~LLFilteredWearableListManager();
 
 	/** LLInventoryObserver implementation
@@ -51,9 +52,9 @@ public:
 	/*virtual*/ void changed(U32 mask);
 
 	/**
-	 * Sets new filter and applies it immediately
+	 * Sets new collector and applies it immediately
 	 */
-	void setFilterMask(U64 mask);
+	void setFilterCollector(LLInventoryCollectFunctor* collector);
 
 	/**
 	 * Populates wearable list with filtered data.
@@ -62,7 +63,7 @@ public:
 
 private:
 	LLInventoryItemsList* mWearableList;
-	U64 mFilterMask;
+	LLInventoryCollectFunctor* mCollector;
 };
 
 #endif //LL_LLFILTEREDWEARABLELIST_H
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index c38d45f0f5..6301ff0d6d 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -372,6 +372,11 @@ bool LLFindWearablesOfType::operator()(LLInventoryCategory* cat, LLInventoryItem
 	return true;
 }
 
+void LLFindWearablesOfType::setType(LLWearableType::EType type)
+{
+	mWearableType = type;
+}
+
 ///----------------------------------------------------------------------------
 /// LLAssetIDMatches 
 ///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 8b96ba29d9..bb365573d7 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -251,6 +251,37 @@ public:
 	
 };
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFindNonLinksByMask
+//
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFindNonLinksByMask : public LLInventoryCollectFunctor
+{
+public:
+	LLFindNonLinksByMask(U64 mask)
+		: mFilterMask(mask)
+	{}
+
+	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+	{
+		if(item && !item->getIsLinkType() && (mFilterMask & (1LL << item->getInventoryType())) )
+		{
+			return true;
+		}
+
+		return false;
+	}
+
+	void setFilterMask(U64 mask)
+	{
+		mFilterMask = mask;
+	}
+
+private:
+	U64 mFilterMask;
+};
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLFindWearables
 //
@@ -272,8 +303,10 @@ public:
 	LLFindWearablesOfType(LLWearableType::EType type) : mWearableType(type) {}
 	virtual ~LLFindWearablesOfType() {}
 	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+	void setType(LLWearableType::EType type);
 
-	const LLWearableType::EType mWearableType;
+private:
+	LLWearableType::EType mWearableType;
 };
 
 /**                    Inventory Collector Functions
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index ae4b288588..8d7a2b33be 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -67,6 +67,7 @@
 #include "llsidepanelappearance.h"
 #include "lltoggleablemenu.h"
 #include "llwearablelist.h"
+#include "llwearableitemslist.h"
 
 static LLRegisterPanelClassWrapper<LLPanelOutfitEdit> t_outfit_edit("panel_outfit_edit");
 
@@ -214,7 +215,10 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
 	mCOFObserver(NULL),
 	mGearMenu(NULL),
 	mCOFDragAndDropObserver(NULL),
-	mInitialized(false)
+	mInitialized(false),
+	mAddWearablesPanel(NULL),
+	mWearableListMaskCollector(NULL),
+	mWearableListTypeCollector(NULL)
 {
 	mSavedFolderState = new LLSaveFolderState();
 	mSavedFolderState->setApply(FALSE);
@@ -236,6 +240,9 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit()
 
 	delete mCOFObserver;
 	delete mCOFDragAndDropObserver;
+
+	delete mWearableListMaskCollector;
+	delete mWearableListTypeCollector;
 }
 
 BOOL LLPanelOutfitEdit::postBuild()
@@ -261,6 +268,7 @@ BOOL LLPanelOutfitEdit::postBuild()
 	mCOFWearables = getChild<LLCOFWearables>("cof_wearables_list");
 	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onOutfitItemSelectionChange, this));
 
+	mCOFWearables->getCOFCallbacks().mAddWearable = boost::bind(&LLPanelOutfitEdit::onAddWearableClicked, this);
 	mCOFWearables->getCOFCallbacks().mEditWearable = boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this);
 	mCOFWearables->getCOFCallbacks().mDeleteWearable = boost::bind(&LLPanelOutfitEdit::onRemoveFromOutfitClicked, this);
 	mCOFWearables->getCOFCallbacks().mMoveWearableCloser = boost::bind(&LLPanelOutfitEdit::moveWearable, this, true);
@@ -268,6 +276,7 @@ BOOL LLPanelOutfitEdit::postBuild()
 
 	mCOFWearables->childSetAction("add_btn", boost::bind(&LLPanelOutfitEdit::toggleAddWearablesPanel, this));
 
+	mAddWearablesPanel = getChild<LLPanel>("add_wearables_panel");
 
 	mInventoryItemsPanel = getChild<LLInventoryPanel>("inventory_items");
 	mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK);
@@ -306,9 +315,12 @@ 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());
 
+	mWearableListMaskCollector = new LLFindNonLinksByMask(ALL_ITEMS_MASK);
+	mWearableListTypeCollector = new LLFindWearablesOfType(LLWearableType::WT_NONE);
+
 	mWearableItemsPanel = getChild<LLPanel>("filtered_wearables_panel");
 	mWearableItemsList = getChild<LLInventoryItemsList>("filtered_wearables_list");
-	mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, ALL_ITEMS_MASK);
+	mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mWearableListMaskCollector);
 
 	return TRUE;
 }
@@ -334,7 +346,8 @@ void LLPanelOutfitEdit::moveWearable(bool closer_to_body)
 
 void LLPanelOutfitEdit::toggleAddWearablesPanel()
 {
-	childSetVisible("add_wearables_panel", !childIsVisible("add_wearables_panel"));
+	BOOL current_visibility = mAddWearablesPanel->getVisible();
+	mAddWearablesPanel->setVisible(!current_visibility);
 }
 
 void LLPanelOutfitEdit::showWearablesFilter()
@@ -407,7 +420,9 @@ 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);
+
+		mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask);
+		mWearableListManager->setFilterCollector(mWearableListMaskCollector);
 	}
 	
 	mSavedFolderState->setApply(TRUE);
@@ -487,6 +502,25 @@ void LLPanelOutfitEdit::onAddToOutfitClicked(void)
 	LLAppearanceMgr::getInstance()->wearItemOnAvatar(selected_id);
 }
 
+void LLPanelOutfitEdit::onAddWearableClicked(void)
+{
+	LLPanelDummyClothingListItem* item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem());
+
+	if(item)
+	{
+		showFilteredWearableItemsList(item->getWearableType());
+	}
+}
+
+void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id)
+{
+	LLViewerInventoryItem* item = gInventory.getLinkedItem(selected_item_id);
+
+	if (item && item->getType() == LLAssetType::AT_BODYPART)
+	{
+		showFilteredWearableItemsList(item->getWearableType());
+	}
+}
 
 void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void)
 {
@@ -722,4 +756,11 @@ void LLPanelOutfitEdit::onGearMenuItemClick(const LLSD& data)
 	}
 }
 
+void LLPanelOutfitEdit::showFilteredWearableItemsList(LLWearableType::EType type)
+{
+	mWearableListTypeCollector->setType(type);
+	mWearableListManager->setFilterCollector(mWearableListTypeCollector);
+	mAddWearablesPanel->setVisible(TRUE);
+}
+
 // EOF
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 1bf69c5606..dbfeb2c375 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -59,6 +59,8 @@ class LLToggleableMenu;
 class LLFilterEditor;
 class LLFilteredWearableListManager;
 class LLMenuGL;
+class LLFindNonLinksByMask;
+class LLFindWearablesOfType;
 
 class LLPanelOutfitEdit : public LLPanel
 {
@@ -103,6 +105,8 @@ public:
 	void onOutfitItemSelectionChange(void);
 	void onRemoveFromOutfitClicked(void);
 	void onEditWearableClicked(void);
+	void onAddWearableClicked(void);
+	void onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id);
 
 	void displayCurrentOutfit();
 	void updateCurrentOutfitName();
@@ -129,6 +133,7 @@ private:
 
 	void onGearButtonClick(LLUICtrl* clicked_button);
 	void onGearMenuItemClick(const LLSD& data);
+	void showFilteredWearableItemsList(LLWearableType::EType type);
 
 
 	LLTextBox*			mCurrentOutfitName;
@@ -141,6 +146,10 @@ private:
 	LLButton*			mFolderViewBtn;
 	LLButton*			mListViewBtn;
 	LLToggleableMenu*	mSaveMenu;
+	LLPanel*			mAddWearablesPanel;
+
+	LLFindNonLinksByMask*  mWearableListMaskCollector;
+	LLFindWearablesOfType* mWearableListTypeCollector;
 
 	LLFilteredWearableListManager* 	mWearableListManager;
 	LLInventoryItemsList* 			mWearableItemsList;
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index fb7577c008..161cd40cfc 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -251,6 +251,11 @@ BOOL LLPanelDummyClothingListItem::postBuild()
 	return TRUE;
 }
 
+LLWearableType::EType LLPanelDummyClothingListItem::getWearableType() const
+{
+	return mWearableType;
+}
+
 LLPanelDummyClothingListItem::LLPanelDummyClothingListItem(LLWearableType::EType w_type)
  : LLPanelWearableListItem(NULL)
  , mWearableType(w_type)
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 7ad1b5a3ad..de024ed220 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -162,6 +162,7 @@ public:
 
 	/*virtual*/ void updateItem();
 	/*virtual*/ BOOL postBuild();
+	LLWearableType::EType getWearableType() const;
 
 protected:
 	LLPanelDummyClothingListItem(LLWearableType::EType w_type);
-- 
cgit v1.2.3