From f55af5fcdfdd0b4520e382d315afefd41c534820 Mon Sep 17 00:00:00 2001
From: Igor Borovkov <iborovkov@productengine.com>
Date: Mon, 29 Mar 2010 14:07:40 +0300
Subject: [PATCH] done EXT-6547 Rename stuff related with Panel Look Info to
 Panel Outfit Edit

renamed panel_look_info.xml to panel_outfit_edit.xml
renamed llpanellookinfo.cpp/llpanellookinfo.h to llpaneloutfitedit.cpp/llpaneloutfitedit.h
renamed LLPanelLookInfo to LLPanelOutfitEdit

Reviewed at https://codereview.productengine.com/secondlife/r/130/

--HG--
branch : product-engine
---
 indra/newview/CMakeLists.txt                  |   4 +-
 indra/newview/llpaneloutfitedit.cpp           | 511 ++++++++++++++++++
 indra/newview/llpaneloutfitedit.h             | 127 +++++
 indra/newview/llsidepanelappearance.cpp       |  32 +-
 indra/newview/llsidepanelappearance.h         |   6 +-
 .../default/xui/en/panel_outfit_edit.xml      | 233 ++++++++
 .../default/xui/en/sidepanel_appearance.xml   |   6 +-
 7 files changed, 895 insertions(+), 24 deletions(-)
 create mode 100644 indra/newview/llpaneloutfitedit.cpp
 create mode 100644 indra/newview/llpaneloutfitedit.h
 create mode 100644 indra/newview/skins/default/xui/en/panel_outfit_edit.xml

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index f45237a73ca..9bdf9d88937 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -317,7 +317,6 @@ set(viewer_SOURCE_FILES
     llpanellandmedia.cpp
     llpanellogin.cpp
     llpanelloginlistener.cpp
-    llpanellookinfo.cpp
     llpanelmaininventory.cpp
     llpanelmediasettingsgeneral.cpp
     llpanelmediasettingspermissions.cpp
@@ -326,6 +325,7 @@ set(viewer_SOURCE_FILES
     llpanelnearbymedia.cpp
     llpanelobject.cpp
     llpanelobjectinventory.cpp
+    llpaneloutfitedit.cpp
     llpaneloutfitsinventory.cpp
     llpanelpeople.cpp
     llpanelpeoplemenus.cpp
@@ -814,7 +814,6 @@ set(viewer_HEADER_FILES
     llpanellandmedia.h
     llpanellogin.h
     llpanelloginlistener.h
-    llpanellookinfo.h
     llpanelmaininventory.h
     llpanelmediasettingsgeneral.h
     llpanelmediasettingspermissions.h
@@ -823,6 +822,7 @@ set(viewer_HEADER_FILES
     llpanelnearbymedia.h
     llpanelobject.h
     llpanelobjectinventory.h
+    llpaneloutfitedit.h
     llpaneloutfitsinventory.h
     llpanelpeople.h
     llpanelpeoplemenus.h
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
new file mode 100644
index 00000000000..6139174da31
--- /dev/null
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -0,0 +1,511 @@
+/**
+ * @file llpaneloutfitedit.cpp
+ * @brief Displays outfit edit information in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2004-2009, 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 "llpaneloutfitedit.h"
+
+// *TODO: reorder includes to match the coding standard
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
+#include "llinventory.h"
+#include "llviewercontrol.h"
+#include "llui.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "llviewerwindow.h"
+#include "llviewerinventory.h"
+#include "llbutton.h"
+#include "llcombobox.h"
+#include "llfiltereditor.h"
+#include "llfloaterinventory.h"
+#include "llinventorybridge.h"
+#include "llinventorymodel.h"
+#include "lluiconstants.h"
+#include "llscrolllistctrl.h"
+#include "lltextbox.h"
+#include "lluictrlfactory.h"
+#include "llsdutil.h"
+#include "llsidepanelappearance.h"
+#include "llwearablelist.h"
+
+static LLRegisterPanelClassWrapper<LLPanelOutfitEdit> t_look("panel_outfit_edit");
+
+const U64 WEARABLE_MASK = (1LL << LLInventoryType::IT_WEARABLE);
+const U64 ATTACHMENT_MASK = (1LL << LLInventoryType::IT_ATTACHMENT) | (1LL << LLInventoryType::IT_OBJECT);
+const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;
+
+class LLInventoryLookObserver : public LLInventoryObserver
+{
+public:
+	LLInventoryLookObserver(LLPanelOutfitEdit *panel) : mPanel(panel) {}
+	virtual ~LLInventoryLookObserver() 
+	{
+		if (gInventory.containsObserver(this))
+		{
+			gInventory.removeObserver(this);
+		}
+	}
+	
+	virtual void changed(U32 mask)
+	{
+		if (mask & (LLInventoryObserver::ADD | LLInventoryObserver::REMOVE))
+		{
+			mPanel->updateLookInfo();
+		}
+	}
+protected:
+	LLPanelOutfitEdit *mPanel;
+};
+
+class LLLookFetchObserver : public LLInventoryFetchDescendentsObserver
+{
+public:
+	LLLookFetchObserver(LLPanelOutfitEdit *panel) :
+	mPanel(panel)
+	{}
+	LLLookFetchObserver() {}
+	virtual void done()
+	{
+		mPanel->lookFetched();
+		if(gInventory.containsObserver(this))
+		{
+			gInventory.removeObserver(this);
+		}
+	}
+private:
+	LLPanelOutfitEdit *mPanel;
+};
+
+
+
+LLPanelOutfitEdit::LLPanelOutfitEdit()
+:	LLPanel(), mLookID(), mFetchLook(NULL), mSearchFilter(NULL),
+mLookContents(NULL), mInventoryItemsPanel(NULL), mAddToLookBtn(NULL),
+mRemoveFromLookBtn(NULL), mLookObserver(NULL), mNumItemsInLook(0)
+{
+	mSavedFolderState = new LLSaveFolderState();
+	mSavedFolderState->setApply(FALSE);
+	
+	mFetchLook = new LLLookFetchObserver(this);
+	mLookObserver = new LLInventoryLookObserver(this);
+	gInventory.addObserver(mLookObserver);
+	
+	mLookItemTypes.reserve(NUM_LOOK_ITEM_TYPES);
+	for (U32 i = 0; i < NUM_LOOK_ITEM_TYPES; i++)
+	{
+		mLookItemTypes.push_back(LLLookItemType());
+	}
+	
+	// TODO: make these strings translatable
+	mLookItemTypes[LIT_ALL] = LLLookItemType("All Items", ALL_ITEMS_MASK);
+	mLookItemTypes[LIT_WEARABLE] = LLLookItemType("Shape & Clothing", WEARABLE_MASK);
+	mLookItemTypes[LIT_ATTACHMENT] = LLLookItemType("Attachments", ATTACHMENT_MASK);
+
+}
+
+LLPanelOutfitEdit::~LLPanelOutfitEdit()
+{
+	delete mSavedFolderState;
+	if (gInventory.containsObserver(mFetchLook))
+	{
+		gInventory.removeObserver(mFetchLook);
+	}
+	delete mFetchLook;
+	
+	if (gInventory.containsObserver(mLookObserver))
+	{
+		gInventory.removeObserver(mLookObserver);
+	}
+	delete mLookObserver;
+}
+
+BOOL LLPanelOutfitEdit::postBuild()
+{
+	// gInventory.isInventoryUsable() no longer needs to be tested per Richard's fix for race conditions between inventory and panels
+		
+	mLookName = getChild<LLTextBox>("curr_look_name"); 
+	
+	/*
+	mLookContents->setDoubleClickCallback(onDoubleClickSpeaker, this);
+	mLookContents->setCommitOnSelectionChange(TRUE);
+	mLookContents->setCommitCallback(boost::bind(&LLPanelActiveSpeakers::handleSpeakerSelect, this, _2));
+	mLookContents->setSortChangedCallback(boost::bind(&LLPanelActiveSpeakers::onSortChanged, this));
+	mLookContents->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+	*/
+	
+	mInventoryItemsPanel = getChild<LLInventoryPanel>("inventory_items");
+	mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK);
+	mInventoryItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+	// mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2));
+	// mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2));
+	
+	LLComboBox* type_filter = getChild<LLComboBox>("inventory_filter");
+	type_filter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1));
+	type_filter->removeall();
+	for (U32 i = 0; i < mLookItemTypes.size(); ++i)
+	{
+		type_filter->add(mLookItemTypes[i].displayName);
+	}
+	type_filter->setCurrentByIndex(LIT_ALL);
+	
+	mSearchFilter = getChild<LLFilterEditor>("look_item_filter");
+	mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2));
+	
+	/* Removing add to look inline button (not part of mvp for viewer 2)
+	LLButton::Params add_params;
+	add_params.name("add_to_look");
+	add_params.click_callback.function(boost::bind(&LLPanelOutfitEdit::onAddToLookClicked, this));
+	add_params.label("+");
+	
+	mAddToLookBtn = LLUICtrlFactory::create<LLButton>(add_params);
+	mAddToLookBtn->setEnabled(FALSE);
+	mAddToLookBtn->setVisible(FALSE); */
+	
+	childSetAction("add_item_btn", boost::bind(&LLPanelOutfitEdit::onAddToLookClicked, this), this);
+
+	mUpBtn = getChild<LLButton>("up_btn");
+	mUpBtn->setEnabled(TRUE);
+	mUpBtn->setClickedCallback(boost::bind(&LLPanelOutfitEdit::onUpClicked, this));
+	
+	mLookContents = getChild<LLScrollListCtrl>("look_items_list");
+	mLookContents->sortByColumn("look_item_sort", TRUE);
+	mLookContents->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onLookItemSelectionChange, this));
+	
+	/*
+	LLButton::Params remove_params;
+	remove_params.name("remove_from_look");
+	remove_params.click_callback.function(boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this));
+	remove_params.label("-"); */
+	
+	//mRemoveFromLookBtn = LLUICtrlFactory::create<LLButton>(remove_params);
+	mRemoveFromLookBtn = getChild<LLButton>("remove_from_look_btn");
+	mRemoveFromLookBtn->setEnabled(FALSE);
+	mRemoveFromLookBtn->setVisible(FALSE);
+	//childSetAction("remove_from_look_btn", boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this), this);
+	mRemoveFromLookBtn->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this));
+	//getChild<LLPanel>("look_info_group_bar")->addChild(mRemoveFromLookBtn); remove_item_btn
+
+	mEditWearableBtn = getChild<LLButton>("edit_wearable_btn");
+	mEditWearableBtn->setEnabled(FALSE);
+	mEditWearableBtn->setVisible(FALSE);
+	mEditWearableBtn->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this));
+	
+	childSetAction("remove_item_btn", boost::bind(&LLPanelOutfitEdit::onRemoveFromLookClicked, this), this);
+	
+	return TRUE;
+}
+
+void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl)
+{
+	LLComboBox* type_filter = dynamic_cast<LLComboBox*>(ctrl);
+	llassert(type_filter);
+	if (type_filter)
+	{
+		U32 curr_filter_type = type_filter->getCurrentIndex();
+		mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask);
+	}
+	
+	mSavedFolderState->setApply(TRUE);
+	mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+	
+	LLOpenFoldersWithSelection opener;
+	mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener);
+	mInventoryItemsPanel->getRootFolder()->scrollToShowSelection();
+	
+	gInventory.startBackgroundFetch();
+}
+
+void LLPanelOutfitEdit::onSearchEdit(const std::string& string)
+{
+	if (mSearchString != string)
+	{
+		mSearchString = string;
+		
+		// Searches are case-insensitive
+		LLStringUtil::toUpper(mSearchString);
+		LLStringUtil::trimHead(mSearchString);
+	}
+	
+	if (mSearchString == "")
+	{
+		mInventoryItemsPanel->setFilterSubString(LLStringUtil::null);
+		
+		// re-open folders that were initially open
+		mSavedFolderState->setApply(TRUE);
+		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+		LLOpenFoldersWithSelection opener;
+		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener);
+		mInventoryItemsPanel->getRootFolder()->scrollToShowSelection();
+	}
+	
+	gInventory.startBackgroundFetch();
+	
+	if (mInventoryItemsPanel->getFilterSubString().empty() && mSearchString.empty())
+	{
+		// current filter and new filter empty, do nothing
+		return;
+	}
+	
+	// save current folder open state if no filter currently applied
+	if (mInventoryItemsPanel->getRootFolder()->getFilterSubString().empty())
+	{
+		mSavedFolderState->setApply(FALSE);
+		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+	}
+	
+	// set new filter string
+	mInventoryItemsPanel->setFilterSubString(mSearchString);
+}
+
+void LLPanelOutfitEdit::onAddToLookClicked(void)
+{
+	LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem();
+	LLFolderViewEventListener* listenerp  = curr_item->getListener();
+	link_inventory_item(gAgent.getID(), listenerp->getUUID(), mLookID, listenerp->getName(),
+						LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
+	updateLookInfo();
+}
+
+
+void LLPanelOutfitEdit::onRemoveFromLookClicked(void)
+{
+	LLUUID id_to_remove = mLookContents->getSelectionInterface()->getCurrentID();
+	
+	LLViewerInventoryItem * item_to_remove = gInventory.getItem(id_to_remove);
+	
+	if (item_to_remove)
+	{
+		// returns null if not a wearable (attachment, etc).
+		const LLWearable* wearable_to_remove = gAgentWearables.getWearableFromAssetID(item_to_remove->getAssetUUID());
+		if (!wearable_to_remove || gAgentWearables.canWearableBeRemoved( wearable_to_remove ))
+		{											 
+			gInventory.purgeObject( id_to_remove );
+			updateLookInfo();
+			mRemoveFromLookBtn->setEnabled(FALSE);
+			if (mRemoveFromLookBtn->getVisible())
+			{
+				mRemoveFromLookBtn->setVisible(FALSE);
+			}
+		}
+	}
+}
+
+
+void LLPanelOutfitEdit::onUpClicked(void)
+{
+	LLUUID inv_id = mLookContents->getSelectionInterface()->getCurrentID();
+	if (inv_id.isNull())
+	{
+		//nothing selected, do nothing
+		return;
+	}
+
+	LLViewerInventoryItem *link_item = gInventory.getItem(inv_id);
+	if (!link_item)
+	{
+		llwarns << "could not find inventory item based on currently worn link." << llendl;
+		return;
+	}
+
+
+	LLUUID asset_id = link_item->getAssetUUID();
+	if (asset_id.isNull())
+	{
+		llwarns << "inventory link has null Asset ID. could not get object reference" << llendl;
+	}
+
+	static const std::string empty = "";
+	LLWearableList::instance().getAsset(asset_id,
+										empty,	// don't care about wearable name
+										link_item->getActualType(),
+										LLSidepanelAppearance::editWearable,
+										(void*)getParentUICtrl());
+}
+
+
+void LLPanelOutfitEdit::onEditWearableClicked(void)
+{
+	LLUUID id_to_edit = mLookContents->getSelectionInterface()->getCurrentID();
+
+	LLViewerInventoryItem * item_to_edit = gInventory.getItem(id_to_edit);
+
+	if (item_to_edit)
+	{
+		// returns null if not a wearable (attachment, etc).
+		LLWearable* wearable_to_edit = gAgentWearables.getWearableFromAssetID(item_to_edit->getAssetUUID());
+		if (!wearable_to_edit || !wearable_to_edit->getPermissions().allowModifyBy(gAgent.getID()) )
+		{											 
+			LLSidepanelAppearance::editWearable(wearable_to_edit, getParent());
+			if (mEditWearableBtn->getVisible())
+			{
+				mEditWearableBtn->setVisible(FALSE);
+			}
+		}
+	}
+}
+
+void LLPanelOutfitEdit::onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+	LLFolderViewItem* current_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem();
+	if (!current_item)
+	{
+		return;
+	}
+	
+	/* Removing add to look inline button (not part of mvp for viewer 2)
+	LLRect btn_rect(current_item->getLocalRect().mRight - 50,
+					current_item->getLocalRect().mTop,
+					current_item->getLocalRect().mRight - 30,
+					current_item->getLocalRect().mBottom);
+	
+	mAddToLookBtn->setRect(btn_rect);
+	mAddToLookBtn->setEnabled(TRUE);
+	if (!mAddToLookBtn->getVisible())
+	{
+		mAddToLookBtn->setVisible(TRUE);
+	}
+	
+	current_item->addChild(mAddToLookBtn); */
+}
+
+void LLPanelOutfitEdit::onLookItemSelectionChange(void)
+{	
+	S32 left_offset = -4;
+	S32 top_offset = -10;
+	LLRect rect = mLookContents->getLastSelectedItem()->getRect();
+	LLRect btn_rect(
+					left_offset + rect.mRight - 50,
+					top_offset  + rect.mTop,
+					left_offset + rect.mRight - 30,
+					top_offset  + rect.mBottom);
+	
+	mEditWearableBtn->setRect(btn_rect);
+	
+	mEditWearableBtn->setEnabled(TRUE);
+	if (!mEditWearableBtn->getVisible())
+	{
+		mEditWearableBtn->setVisible(TRUE);
+	}
+	//mLookContents->addChild(mRemoveFromLookBtn);
+}
+
+void LLPanelOutfitEdit::changed(U32 mask)
+{
+}
+
+void LLPanelOutfitEdit::lookFetched(void)
+{
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t item_array;
+
+	// collectDescendentsIf takes non-const reference:
+	LLFindCOFValidItems is_cof_valid;
+	gInventory.collectDescendentsIf(mLookID,
+									cat_array,
+									item_array,
+									LLInventoryModel::EXCLUDE_TRASH,
+									is_cof_valid);
+	for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+		 iter != item_array.end();
+		 iter++)
+	{
+		const LLViewerInventoryItem *item = (*iter);
+		
+		LLSD row;
+		row["id"] = item->getUUID();
+		LLSD& columns = row["columns"];
+		columns[0]["column"] = "look_item";
+		columns[0]["type"] = "text";
+		columns[0]["value"] = item->getName();
+		columns[1]["column"] = "look_item_sort";
+		columns[1]["type"] = "text"; // TODO: multi-wearable sort "type" should go here.
+		columns[1]["value"] = "BAR"; // TODO: Multi-wearable sort index should go here
+		
+		mLookContents->addElement(row);
+	}
+	
+	if (mLookContents->getItemCount() != mNumItemsInLook)
+	{
+		mNumItemsInLook = mLookContents->getItemCount();
+		LLAppearanceManager::instance().updateCOF(mLookID);
+	}
+}
+
+void LLPanelOutfitEdit::updateLookInfo()
+{	
+	if (getVisible())
+	{
+		mLookContents->clearRows();
+		
+		LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+		folders.push_back(mLookID);
+		mFetchLook->fetchDescendents(folders);
+		if (mFetchLook->isEverythingComplete())
+		{
+			mFetchLook->done();
+		}
+		else
+		{
+			gInventory.addObserver(mFetchLook);
+		}
+	}
+}
+
+void LLPanelOutfitEdit::displayLookInfo(const LLInventoryCategory* pLook)
+{
+	if (!pLook)
+	{
+		return;
+	}
+	
+	if (!getVisible())
+	{
+		setVisible(TRUE);
+	}
+
+	if (mLookID != pLook->getUUID())
+	{
+		mLookID = pLook->getUUID();
+		mLookName->setText("Look: " + pLook->getName());
+		updateLookInfo();
+	}
+}
+
+void LLPanelOutfitEdit::reset()
+{
+	mLookID.setNull();
+}
+
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
new file mode 100644
index 00000000000..09ec51c056c
--- /dev/null
+++ b/indra/newview/llpaneloutfitedit.h
@@ -0,0 +1,127 @@
+/** 
+ * @file llpaneloutfitedit.h
+ * @brief Displays outfit edit information in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2004-2009, 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_LLPANELOUTFITEDIT_H
+#define LL_LLPANELOUTFITEDIT_H
+
+#include "llpanel.h"
+
+#include "v3dmath.h"
+#include "lluuid.h"
+
+#include "lliconctrl.h"
+
+#include "llremoteparcelrequest.h"
+#include "llinventory.h"
+#include "llinventorymodel.h"
+
+class LLButton;
+class LLTextBox;
+class LLInventoryCategory;
+class LLInventoryLookObserver;
+class LLInventoryPanel;
+class LLSaveFolderState;
+class LLFolderViewItem;
+class LLScrollListCtrl;
+class LLLookFetchObserver;
+class LLFilterEditor;
+
+class LLPanelOutfitEdit : public LLPanel
+{
+public:
+	
+	// NOTE: initialize mLookItemTypes at the index of any new enum you add in the LLPanelOutfitEdit() constructor
+	typedef enum e_look_item_type
+	{
+		LIT_ALL = 0,
+		LIT_WEARABLE, // clothing or shape
+		LIT_ATTACHMENT,
+		NUM_LOOK_ITEM_TYPES
+	} ELookItemType; 
+	
+	struct LLLookItemType {
+		std::string displayName;
+		U64 inventoryMask;
+		LLLookItemType() : displayName("NONE"), inventoryMask(0) {}
+		LLLookItemType(std::string name, U64 mask) : displayName(name), inventoryMask(mask) {}
+	};
+	
+	LLPanelOutfitEdit();
+	/*virtual*/ ~LLPanelOutfitEdit();
+
+	/*virtual*/ BOOL postBuild();
+	/*virtual*/ void changed(U32 mask);
+
+	void reset();
+		// Ignore all old information, useful if you are 
+		// recycling an existing dialog and need to clear it.
+
+	/*virtual*/ void setParcelID(const LLUUID& parcel_id);
+		// Sends a request for data about the given parcel, which will
+		// only update the location if there is none already available.
+	
+	void onTypeFilterChanged(LLUICtrl* ctrl);
+	void onSearchEdit(const std::string& string);
+	void onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+	void onAddToLookClicked(void);
+	void onLookItemSelectionChange(void);
+	void onRemoveFromLookClicked(void);
+	void onEditWearableClicked(void);
+	void onUpClicked(void);
+
+	void displayLookInfo(const LLInventoryCategory* pLook);
+	
+	void lookFetched(void);
+	
+	void updateLookInfo(void);
+
+private:
+
+	LLUUID				mLookID;
+	LLTextBox*			mLookName;
+	LLScrollListCtrl*	mLookContents;
+	LLInventoryPanel*	mInventoryItemsPanel;
+	LLFilterEditor*		mSearchFilter;
+	LLSaveFolderState*	mSavedFolderState;
+	std::string			mSearchString;
+	LLButton*			mAddToLookBtn;
+	LLButton*			mRemoveFromLookBtn;
+	LLButton*			mUpBtn;
+	LLButton*			mEditWearableBtn;
+	S32					mNumItemsInLook;
+	
+	LLLookFetchObserver*		mFetchLook;
+	LLInventoryLookObserver*	mLookObserver;
+	std::vector<LLLookItemType> mLookItemTypes;
+};
+
+#endif // LL_LLPANELOUTFITEDIT_H
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 9a37af49160..90c0cd54673 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -93,7 +93,7 @@ LLSidepanelAppearance::LLSidepanelAppearance() :
 	LLPanel(),
 	mFilterSubString(LLStringUtil::null),
 	mFilterEditor(NULL),
-	mLookInfo(NULL),
+	mOutfitEdit(NULL),
 	mCurrOutfitPanel(NULL)
 {
 }
@@ -129,10 +129,10 @@ BOOL LLSidepanelAppearance::postBuild()
 	mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory"));
 	mPanelOutfitsInventory->setParent(this);
 
-	mLookInfo = dynamic_cast<LLPanelLookInfo*>(getChild<LLPanel>("panel_look_info"));
-	if (mLookInfo)
+	mOutfitEdit = dynamic_cast<LLPanelOutfitEdit*>(getChild<LLPanel>("panel_outfit_edit"));
+	if (mOutfitEdit)
 	{
-		LLButton* back_btn = mLookInfo->getChild<LLButton>("back_btn");
+		LLButton* back_btn = mOutfitEdit->getChild<LLButton>("back_btn");
 		if (back_btn)
 		{
 			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onBackButtonClicked, this));
@@ -177,7 +177,7 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
 	if(key.size() == 0)
 		return;
 
-	toggleLookInfoPanel(TRUE);
+	toggleOutfitEditPanel(TRUE);
 	updateVerbs();
 	
 	mLookInfoType = key["type"].asString();
@@ -186,7 +186,7 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
 	{
 		LLInventoryCategory *pLook = gInventory.getCategory(key["id"].asUUID());
 		if (pLook)
-			mLookInfo->displayLookInfo(pLook);
+			mOutfitEdit->displayLookInfo(pLook);
 	}
 }
 
@@ -241,9 +241,9 @@ void LLSidepanelAppearance::onEditAppearanceButtonClicked()
 
 void LLSidepanelAppearance::onEditButtonClicked()
 {
-	toggleLookInfoPanel(FALSE);
+	toggleOutfitEditPanel(FALSE);
 	toggleWearableEditPanel(TRUE, NULL);
-	/*if (mLookInfo->getVisible())
+	/*if (mOutfitEdit->getVisible())
 	  {
 	  }
 	  else
@@ -254,7 +254,7 @@ void LLSidepanelAppearance::onEditButtonClicked()
 
 void LLSidepanelAppearance::onNewOutfitButtonClicked()
 {
-	if (!mLookInfo->getVisible())
+	if (!mOutfitEdit->getVisible())
 	{
 		mPanelOutfitsInventory->onSave();
 	}
@@ -263,22 +263,22 @@ void LLSidepanelAppearance::onNewOutfitButtonClicked()
 
 void LLSidepanelAppearance::onBackButtonClicked()
 {
-	toggleLookInfoPanel(FALSE);
+	toggleOutfitEditPanel(FALSE);
 }
 
 void LLSidepanelAppearance::onEditWearBackClicked()
 {
 	mEditWearable->saveChanges();
 	toggleWearableEditPanel(FALSE, NULL);
-	toggleLookInfoPanel(TRUE);
+	toggleOutfitEditPanel(TRUE);
 }
 
-void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible)
+void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible)
 {
-	if (!mLookInfo)
+	if (!mOutfitEdit)
 		return;
 
-	mLookInfo->setVisible(visible);
+	mOutfitEdit->setVisible(visible);
 	if (mPanelOutfitsInventory) mPanelOutfitsInventory->setVisible(!visible);
 	mFilterEditor->setVisible(!visible);
 	mEditBtn->setVisible(!visible);
@@ -305,7 +305,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we
 
 void LLSidepanelAppearance::updateVerbs()
 {
-	bool is_look_info_visible = mLookInfo->getVisible();
+	bool is_look_info_visible = mOutfitEdit->getVisible();
 
 	if (mPanelOutfitsInventory && !is_look_info_visible)
 	{
@@ -344,7 +344,7 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name)
 void LLSidepanelAppearance::editWearable(LLWearable *wearable, void *data)
 {
 	LLSidepanelAppearance *panel = (LLSidepanelAppearance*) data;
-	panel->toggleLookInfoPanel(FALSE);
+	panel->toggleOutfitEditPanel(FALSE);
 	panel->toggleWearableEditPanel(TRUE, wearable);
 }
 
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index aa2e67fd16f..1d78e92a84e 100644
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -36,7 +36,7 @@
 #include "llinventoryobserver.h"
 
 #include "llinventory.h"
-#include "llpanellookinfo.h"
+#include "llpaneloutfitedit.h"
 
 class LLFilterEditor;
 class LLCurrentlyWornFetchObserver;
@@ -71,12 +71,12 @@ class LLSidepanelAppearance : public LLPanel
 	void onEditButtonClicked();
 	void onBackButtonClicked();
 	void onEditWearBackClicked();
-	void toggleLookInfoPanel(BOOL visible);
+	void toggleOutfitEditPanel(BOOL visible);
 	void toggleWearableEditPanel(BOOL visible, LLWearable* wearable);
 
 	LLFilterEditor*			mFilterEditor;
 	LLPanelOutfitsInventory* mPanelOutfitsInventory;
-	LLPanelLookInfo*		mLookInfo;
+	LLPanelOutfitEdit*		mOutfitEdit;
 	LLPanelEditWearable*	mEditWearable;
 
 	LLButton*					mOpenOutfitBtn;
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
new file mode 100644
index 00000000000..d4924562fb8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+  background_visible="true"
+  border="false"
+	height="570"
+	follows="all"
+	label="Look Info"
+	layout="topleft"
+	name="look_info"
+	width="320">
+	<panel.string
+		name="not_available">
+		(N\A)
+	</panel.string>
+	<panel.string
+		name="unknown">
+		(unknown)
+	</panel.string>
+	<panel
+		background_visible="true"
+		bevel_style="none"
+		follows="left|top|right|bottom"
+		height="530"
+		label="Outfit"
+		layout="topleft"
+		name="look_management_panel"
+		width="320">
+        <panel
+          follows="left|right|top"
+            header_visible="false"
+            layout="topleft"
+            min_height="300"
+            name="look_group"
+            title="Outfit Group"
+          top="0">
+            <panel
+                follows="left|right|top"
+                height="210"
+                layout="topleft"
+                top_pad="0"
+                name="look_info_group_bar"
+                width="295">
+                <text
+                    type="string"
+                    length="1"
+                    follows="left|top"
+                    height="20"
+                    layout="topleft"
+                    mouse_opaque="false"
+                    name="curr_look_name"
+                    width="175">
+                    Look: [LOOK]
+                </text>
+                <button
+                    follows="left|top"
+                    height="20"
+                    label="Wear"
+                    layout="topleft"
+                    name="wear_look_btn"
+                    left_pad="5"
+                    top_pad="-24"
+                    width="65" />
+                <button
+                    follows="left|top"
+                    height="20"
+                    layout="topleft"
+                    left_pad="5"
+                    name="back_btn"
+                    width="20" />
+            </panel>
+        </panel>
+
+        <panel
+            follows="left|right|top"
+          height="200"
+          layout="topleft"
+          name="outfit_display"
+          top_pad="10"
+          width="320">
+          
+              <scroll_list
+                  width="285"
+                  column_padding="0"
+                  draw_heading="false"
+                  draw_stripes="false"
+                  follows="left|top|bottom|right"
+                  layout="topleft"
+                  name="look_items_list"
+                  search_column="1"
+                  sort_column="2"
+                  left="0"
+                  height="200"
+                  top_pad="0">
+                  <scroll_list.columns
+                      label="Look Item"
+                      name="look_item"
+                      width="285" />
+                  <scroll_list.columns
+                      label="Outfit Item Sort"
+                      width="0"
+                      sort_column="look_item_sort"
+                      name="look_item_sort" />
+              </scroll_list>
+              <button
+                  follows="left|top|right"
+                  height="20"
+                  label="-"
+                  left_pad="0"
+                  layout="topleft"
+                  name="edit_wearable_btn"
+                  width="20" />
+        </panel>
+        <panel
+          follows="all"
+            header_visible="false"
+            min_height="100"
+          left="0"
+            name="inventory_group"
+            title="My Inventory"
+          top_pad="10"
+          width="230">
+            <panel
+                follows="left|right|top"
+                height="270"
+                name="lower_look_accordion"
+                width="295">
+                <panel
+                    follows="left|right|top"
+                    height="20"
+                    layout="topleft"
+                    name="inventory_bar"
+                    width="295">
+                    <text
+                        type="string"
+                        length="1"
+                        follows="left|top"
+                        height="20"
+                        layout="topleft"
+                        mouse_opaque="false"
+                        name="inventory_info_text"
+                        width="100">
+                        My Inventory
+                    </text>
+                    <combo_box
+                        follows="left"
+                        height="20"
+                        layout="topleft"
+                        left_pad="0"
+                        top_pad="-24"
+                        name="inventory_filter"
+                        tool_tip="Only show the selected inventory types"
+                        width="185" />
+                </panel>
+                <panel
+                    follows="left|right|top"
+                    height="20"
+                    layout="topleft"
+                    name="look_item_filter_bar"
+                    width="295">
+                    <filter_editor
+                        background_image="TextField_Search_Off"
+                        follows="left|top|right"
+                        font="SansSerif"
+                        label="Outfit Item Filter"
+                        layout="topleft"
+                        left="0"
+                        top_pad="0"
+                        width="270"
+                        height="20"
+                        name="look_item_filter"
+                        text_color="black"
+                        text_pad_left="25" />
+                </panel>
+                <panel
+                    follows="all"
+                    height="230"
+                    layout="topleft"
+                    name="inventory_panel"
+                    width="285">
+                    <inventory_panel
+                        allow_multi_select="true"
+                        border="true"
+                        follows="left|top|right|bottom"
+                        height="230"
+                        mouse_opaque="false"
+                        name="inventory_items"
+                        width="285"/>
+                </panel>
+            </panel>
+        </panel>
+	</panel>
+	<panel
+		follows="left|right|bottom"
+		height="30"
+		layout="topleft"
+		left="5"
+		top_pad="0"
+		name="button_bar"
+		width="295">
+		<button
+			follows="top|left|right"
+			height="25"
+			label="Add"
+			left="0"
+			layout="topleft"
+			name="add_item_btn"
+			width="90" />
+		<button
+			follows="left|right"
+			height="25"
+			left_pad="0"
+			label="Remove"
+			layout="topleft"
+			name="remove_item_btn"
+			width="90" />
+		<button
+			follows="top|left|right"
+			height="25"
+			label="UP"
+			left_pad="0"
+			layout="topleft"
+			name="up_btn"
+			width="55" />
+		<button
+			follows="left|top|right"
+			height="25"
+			label="DOWN"
+			left_pad="0"
+			layout="topleft"
+			name="down_btn"
+			width="60" />
+	</panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
index b3d55fec65d..735635f1a0e 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -102,12 +102,12 @@ width="333">
 		name="newlook_btn"
 		 width="100" />-->
    <panel
-   class="panel_look_info"
-   filename="panel_look_info.xml"
+   class="panel_outfit_edit"
+   filename="panel_outfit_edit.xml"
    follows="all"
    layout="topleft"
    left="0"
-   name="panel_look_info"
+   name="panel_outfit_edit"
    top="35"
    visible="false" />
    <panel
-- 
GitLab