diff options
Diffstat (limited to 'indra/newview/llpaneloutfitedit.cpp')
| -rw-r--r-- | indra/newview/llpaneloutfitedit.cpp | 2898 | 
1 files changed, 1449 insertions, 1449 deletions
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index abb8178b47..9687c739fa 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -1,1449 +1,1449 @@ -/** - * @file llpaneloutfitedit.cpp - * @brief Displays outfit edit information in Side Tray. - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpaneloutfitedit.h" - -// *TODO: reorder includes to match the coding standard -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "llappearancemgr.h" -#include "lloutfitobserver.h" -#include "llcofwearables.h" -#include "llfilteredwearablelist.h" -#include "llfolderview.h" -#include "llinventory.h" -#include "llinventoryitemslist.h" -#include "llviewercontrol.h" -#include "llui.h" -#include "llfloater.h" -#include "llfloaterreg.h" -#include "llinventoryfunctions.h" -#include "llinventorypanel.h" -#include "llviewermenu.h" -#include "llviewerwindow.h" -#include "llviewerinventory.h" -#include "llbutton.h" -#include "llcombobox.h" -#include "llfiltereditor.h" -#include "llinventorybridge.h" -#include "llinventorymodel.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llloadingindicator.h" -#include "llmenubutton.h" -#include "llpaneloutfitsinventory.h" -#include "lluiconstants.h" -#include "llscrolllistctrl.h" -#include "lltextbox.h" -#include "lltoggleablemenu.h" -#include "lltrans.h" -#include "lluictrlfactory.h" -#include "llsdutil.h" -#include "llsidepanelappearance.h" -#include "lltoggleablemenu.h" -#include "llvoavatarself.h" -#include "llwearablelist.h" -#include "llwearableitemslist.h" -#include "llwearabletype.h" -#include "llweb.h" - -static LLPanelInjector<LLPanelOutfitEdit> t_outfit_edit("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; - -static const std::string REVERT_BTN("revert_btn"); -static const std::string SAVE_AS_BTN("save_as_btn"); -static const std::string SAVE_BTN("save_btn"); - - -/////////////////////////////////////////////////////////////////////////////// -// LLShopURLDispatcher -/////////////////////////////////////////////////////////////////////////////// - -class LLShopURLDispatcher -{ -public: -	std::string resolveURL(LLWearableType::EType wearable_type, ESex sex); -	std::string resolveURL(LLAssetType::EType asset_type, ESex sex); -}; - -std::string LLShopURLDispatcher::resolveURL(LLWearableType::EType wearable_type, ESex sex) -{ -	const std::string prefix = "MarketplaceURL"; -	const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female"; -	const std::string type_str = LLWearableType::getInstance()->getTypeName(wearable_type); - -	std::string setting_name = prefix; - -	switch (wearable_type) -	{ -	case LLWearableType::WT_ALPHA: -	case LLWearableType::WT_NONE: -	case LLWearableType::WT_INVALID:	// just in case, this shouldn't happen -	case LLWearableType::WT_COUNT:		// just in case, this shouldn't happen -		break; - -	default: -		setting_name += '_'; -		setting_name += type_str; -		setting_name += sex_str; -		break; -	} - -	return gSavedSettings.getString(setting_name); -} - -std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex sex) -{ -	const std::string prefix = "MarketplaceURL"; -	const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female"; -	const std::string type_str = LLAssetType::lookup(asset_type); - -	std::string setting_name = prefix; - -	switch (asset_type) -	{ -	case LLAssetType::AT_CLOTHING: -	case LLAssetType::AT_OBJECT: -	case LLAssetType::AT_BODYPART: -		setting_name += '_'; -		setting_name += type_str; -		setting_name += sex_str; -		break; - -	// to suppress warnings -	default: -		break; -	} - -	return gSavedSettings.getString(setting_name); -} - -/////////////////////////////////////////////////////////////////////////////// -// LLPanelOutfitEditGearMenu -/////////////////////////////////////////////////////////////////////////////// - -class LLPanelOutfitEditGearMenu -{ -public: -	static LLToggleableMenu* create() -	{ -		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - -		registrar.add("Wearable.Create", boost::bind(onCreate, _2)); - -		llassert(LLMenuGL::sMenuContainer != NULL); -		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( -			"menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); -		llassert(menu); -		if (menu) -		{ -			populateCreateWearableSubmenus(menu); -		} - -		return menu; -	} - -private: -	static void onCreate(const LLSD& param) -	{ -		LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(param.asString()); -		if (type == LLWearableType::WT_NONE) -		{ -			LL_WARNS() << "Invalid wearable type" << LL_ENDL; -			return; -		} - -		LLAgentWearables::createWearable(type, true); -	} - -	// Populate the menu with items like "New Skin", "New Pants", etc. -	static void populateCreateWearableSubmenus(LLMenuGL* menu) -	{ -		LLView* menu_clothes	= gMenuHolder->getChildView("COF.Gear.New_Clothes", false); -		LLView* menu_bp			= gMenuHolder->getChildView("COF.Gear.New_Body_Parts", false); -		LLWearableType * wearable_type_inst = LLWearableType::getInstance(); - -		for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i) -		{ -			LLWearableType::EType type = (LLWearableType::EType) i; -			const std::string& type_name = wearable_type_inst->getTypeName(type); - -			LLMenuItemCallGL::Params p; -			p.name = type_name; -			p.label = LLTrans::getString(wearable_type_inst->getTypeDefaultNewName(type)); -			p.on_click.function_name = "Wearable.Create"; -			p.on_click.parameter = LLSD(type_name); - -			LLView* parent = wearable_type_inst->getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp; -			LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); -		} -	} -}; - -/////////////////////////////////////////////////////////////////////////////// -// LLAddWearablesGearMenu -/////////////////////////////////////////////////////////////////////////////// - -class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu> -{ -public: -	static LLToggleableMenu* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel) -	{ -		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - -		llassert(flat_list); -		llassert(inventory_panel); - -		LLHandle<LLView> flat_list_handle = flat_list->getHandle(); -		LLHandle<LLPanel> inventory_panel_handle = inventory_panel->getHandle(); - -		registrar.add("AddWearable.Gear.Sort", boost::bind(onSort, flat_list_handle, inventory_panel_handle, _2)); -		enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2)); -		enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2)); - -		llassert(LLMenuGL::sMenuContainer != NULL); -		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( -			"menu_add_wearable_gear.xml", -			LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); - -		return menu; -	} - -private: -	static void onSort(LLHandle<LLView> flat_list_handle, -					   LLHandle<LLPanel> inventory_panel_handle, -					   LLSD::String sort_order_str) -	{ -		if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return; - -		LLWearableItemsList* flat_list = dynamic_cast<LLWearableItemsList*>(flat_list_handle.get()); -		LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get()); - -		if (!flat_list || !inventory_panel) return; - -		LLWearableItemsList::ESortOrder	sort_order; - -		if ("by_most_recent" == sort_order_str) -		{ -			sort_order = LLWearableItemsList::E_SORT_BY_MOST_RECENT; -		} -		else if ("by_name" == sort_order_str) -		{ -			sort_order = LLWearableItemsList::E_SORT_BY_NAME; -		} -		else if ("by_type" == sort_order_str) -		{ -			sort_order = LLWearableItemsList::E_SORT_BY_TYPE_NAME; -		} -		else -		{ -			LL_WARNS() << "Unrecognized sort order action" << LL_ENDL; -			return; -		} - -		if (inventory_panel->getVisible()) -		{ -			inventory_panel->getFolderViewModel()->setSorter(sort_order); -		} -		else -		{ -			flat_list->setSortOrder(sort_order); -		} -	} - -	static bool onCheck(LLHandle<LLView> flat_list_handle, -						LLHandle<LLPanel> inventory_panel_handle, -						LLSD::String sort_order_str) -	{ -		if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return false; - -		LLWearableItemsList* flat_list = dynamic_cast<LLWearableItemsList*>(flat_list_handle.get()); -		LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get()); - -		if (!inventory_panel || !flat_list) return false; - -		// Inventory panel uses its own sort order independent from -		// flat list view so this flag is used to distinguish between -		// currently visible "tree" or "flat" representation of inventory. -		bool inventory_tree_visible = inventory_panel->getVisible(); - -		if (inventory_tree_visible) -		{ -			U32 sort_order = inventory_panel->getSortOrder(); - -			if ("by_most_recent" == sort_order_str) -			{ -				return LLWearableItemsList::E_SORT_BY_MOST_RECENT & sort_order; -			} -			else if ("by_name" == sort_order_str) -			{ -				// If inventory panel is not sorted by date then it is sorted by name. -				return LLWearableItemsList::E_SORT_BY_MOST_RECENT & ~sort_order; -			} -			LL_WARNS() << "Unrecognized inventory panel sort order" << LL_ENDL; -		} -		else -		{ -			LLWearableItemsList::ESortOrder	sort_order = flat_list->getSortOrder(); - -			if ("by_most_recent" == sort_order_str) -			{ -				return LLWearableItemsList::E_SORT_BY_MOST_RECENT == sort_order; -			} -			else if ("by_name" == sort_order_str) -			{ -				return LLWearableItemsList::E_SORT_BY_NAME == sort_order; -			} -			else if ("by_type" == sort_order_str) -			{ -				return LLWearableItemsList::E_SORT_BY_TYPE_NAME == sort_order; -			} -			LL_WARNS() << "Unrecognized wearable list sort order" << LL_ENDL; -		} -		return false; -	} - -	static bool onVisible(LLHandle<LLPanel> inventory_panel_handle, -						  LLSD::String sort_order_str) -	{ -		if (inventory_panel_handle.isDead()) return false; - -		LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get()); - -		// Enable sorting by type only for the flat list of items -		// because inventory panel doesn't support this kind of sorting. -		return ( "by_type" == sort_order_str ) -				&&	( !inventory_panel || !inventory_panel->getVisible() ); -	} -}; - -/////////////////////////////////////////////////////////////////////////////// -// LLCOFDragAndDropObserver -/////////////////////////////////////////////////////////////////////////////// - -class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver -{ -public: -	LLCOFDragAndDropObserver(LLInventoryModel* model); - -	virtual ~LLCOFDragAndDropObserver(); - -	virtual void done(); - -private: -	LLInventoryModel* mModel; -}; - -inline LLCOFDragAndDropObserver::LLCOFDragAndDropObserver(LLInventoryModel* model): -		mModel(model) -{ -	if (model != NULL) -	{ -		model->addObserver(this); -	} -} - -inline LLCOFDragAndDropObserver::~LLCOFDragAndDropObserver() -{ -	if (mModel != NULL && mModel->containsObserver(this)) -	{ -		mModel->removeObserver(this); -	} -} - -void LLCOFDragAndDropObserver::done() -{ -	LLAppearanceMgr::instance().updateAppearanceFromCOF(); -} - -/////////////////////////////////////////////////////////////////////////////// -// LLPanelOutfitEdit -/////////////////////////////////////////////////////////////////////////////// - -LLPanelOutfitEdit::LLPanelOutfitEdit() -:	LLPanel(),  -	mSearchFilter(NULL), -	mCOFWearables(NULL), -	mInventoryItemsPanel(NULL), -	mGearMenu(NULL), -	mAddWearablesGearMenu(NULL), -	mCOFDragAndDropObserver(NULL), -	mInitialized(false), -	mAddWearablesPanel(NULL), -	mFolderViewFilterCmbBox(NULL), -	mListViewFilterCmbBox(NULL), -	mWearableListManager(NULL), -	mPlusBtn(NULL), -	mWearablesGearMenuBtn(NULL), -	mGearMenuBtn(NULL) -{ -	mSavedFolderState = new LLSaveFolderState(); -	mSavedFolderState->setApply(false); -	 - -	LLOutfitObserver& observer = LLOutfitObserver::instance(); -	observer.addBOFReplacedCallback(boost::bind(&LLPanelOutfitEdit::updateCurrentOutfitName, this)); -	observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); -	observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); -	observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitEdit::onCOFChanged, this)); - -	gAgentWearables.addLoadingStartedCallback(boost::bind(&LLPanelOutfitEdit::onOutfitChanging, this, true)); -	gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitEdit::onOutfitChanging, this, false)); -	 -	mFolderViewItemTypes.reserve(NUM_FOLDER_VIEW_ITEM_TYPES); -	for (U32 i = 0; i < NUM_FOLDER_VIEW_ITEM_TYPES; i++) -	{ -		mFolderViewItemTypes.push_back(LLLookItemType()); -	} - -} - -LLPanelOutfitEdit::~LLPanelOutfitEdit() -{ -	delete mWearableListManager; -	delete mSavedFolderState; - -	delete mCOFDragAndDropObserver; - -	while (!mListViewItemTypes.empty()) { -		delete mListViewItemTypes.back(); -		mListViewItemTypes.pop_back(); -	} -} - -bool LLPanelOutfitEdit::postBuild() -{ -	// gInventory.isInventoryUsable() no longer needs to be tested per Richard's fix for race conditions between inventory and panels -	 -	mFolderViewItemTypes[FVIT_ALL] = LLLookItemType(getString("Filter.All"), ALL_ITEMS_MASK); -	mFolderViewItemTypes[FVIT_WEARABLE] = LLLookItemType(getString("Filter.Clothes/Body"), WEARABLE_MASK); -	mFolderViewItemTypes[FVIT_ATTACHMENT] = LLLookItemType(getString("Filter.Objects"), ATTACHMENT_MASK); - -	//order is important, see EListViewItemType for order information -	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.All"), new LLFindNonLinksByMask(ALL_ITEMS_MASK))); -	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Clothing"), new LLIsTypeActual(LLAssetType::AT_CLOTHING))); -	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Bodyparts"), new LLIsTypeActual(LLAssetType::AT_BODYPART))); -	mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Objects"), new LLFindNonLinksByMask(ATTACHMENT_MASK)));; -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shape"), new LLFindActualWearablesOfType(LLWearableType::WT_SHAPE))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skin"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIN))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("hair"), new LLFindActualWearablesOfType(LLWearableType::WT_HAIR))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("eyes"), new LLFindActualWearablesOfType(LLWearableType::WT_EYES))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SHIRT))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("pants"), new LLFindActualWearablesOfType(LLWearableType::WT_PANTS))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shoes"), new LLFindActualWearablesOfType(LLWearableType::WT_SHOES))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("socks"), new LLFindActualWearablesOfType(LLWearableType::WT_SOCKS))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("jacket"), new LLFindActualWearablesOfType(LLWearableType::WT_JACKET))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("gloves"), new LLFindActualWearablesOfType(LLWearableType::WT_GLOVES))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("undershirt"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERSHIRT))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("underpants"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERPANTS))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIRT))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("alpha"), new LLFindActualWearablesOfType(LLWearableType::WT_ALPHA))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("tattoo"), new LLFindActualWearablesOfType(LLWearableType::WT_TATTOO))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("physics"), new LLFindActualWearablesOfType(LLWearableType::WT_PHYSICS))); -	mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("universal"), new LLFindActualWearablesOfType(LLWearableType::WT_UNIVERSAL))); - -	mCurrentOutfitName = getChild<LLTextBox>("curr_outfit_name");  -	mStatus = getChild<LLTextBox>("status"); - -	mFolderViewBtn = getChild<LLButton>("folder_view_btn"); -	mListViewBtn = getChild<LLButton>("list_view_btn"); - -	childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL); -	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL); -	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL); -	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL); -	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL); -	childSetCommitCallback("shop_btn_1", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL); -	childSetCommitCallback("shop_btn_2", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL); - -	setVisibleCallback(boost::bind(&LLPanelOutfitEdit::onVisibilityChanged, this, _2)); - -	mWearablesGearMenuBtn = getChild<LLMenuButton>("wearables_gear_menu_btn"); -	mGearMenuBtn = getChild<LLMenuButton>("gear_menu_btn"); - -	mCOFWearables = findChild<LLCOFWearables>("cof_wearables_list"); -	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, 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); -	mCOFWearables->getCOFCallbacks().mMoveWearableFurther = boost::bind(&LLPanelOutfitEdit::moveWearable, this, false); - -	mAddWearablesPanel = getChild<LLPanel>("add_wearables_panel"); - -	mInventoryItemsPanel = getChild<LLInventoryPanel>("folder_view"); -	mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK); -	mInventoryItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -	mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this)); -	mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this)); - -	mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel()); - -	mFolderViewFilterCmbBox = getChild<LLComboBox>("folder_view_filter_combobox"); -	mFolderViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onFolderViewFilterCommitted, this, _1)); -	mFolderViewFilterCmbBox->removeall(); -	for (U32 i = 0; i < mFolderViewItemTypes.size(); ++i) -	{ -		mFolderViewFilterCmbBox->add(mFolderViewItemTypes[i].displayName); -	} -	mFolderViewFilterCmbBox->setCurrentByIndex(FVIT_ALL); -	 -	mListViewFilterCmbBox = getChild<LLComboBox>("list_view_filter_combobox"); -	mListViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onListViewFilterCommitted, this, _1)); -	mListViewFilterCmbBox->removeall(); -	for (U32 i = 0; i < mListViewItemTypes.size(); ++i) -	{ -		mListViewFilterCmbBox->add(mListViewItemTypes[i]->displayName); -	} -	mListViewFilterCmbBox->setCurrentByIndex(LVIT_ALL); - -	mSearchFilter = getChild<LLFilterEditor>("look_item_filter"); -	mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2)); - -	childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::onAddMoreButtonClicked, this)); - -	mPlusBtn = getChild<LLButton>("plus_btn"); -	mPlusBtn->setClickedCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this)); - -	childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); - -	/* -	 * By default AT_CLOTHING are sorted by (in in MY OUTFITS): -	 *  - by type (types order determined in LLWearableType::EType) -	 *  - each LLWearableType::EType by outer layer on top -	 * -	 * In Add More panel AT_CLOTHING should be sorted in a such way: -	 *  - by type (types order determined in LLWearableType::EType) -	 *  - each LLWearableType::EType by name (EXT-8205) -	*/ -	mWearableListViewItemsComparator = new LLWearableItemTypeNameComparator(); -	mWearableListViewItemsComparator->setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANK_1, false, true); - -	mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel"); -	mWearableItemsList = getChild<LLWearableItemsList>("list_view"); -	mWearableItemsList->setCommitOnSelectionChange(true); -	mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this)); -	mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this)); - -	mWearableItemsList->setComparator(mWearableListViewItemsComparator); - -	// Creating "Add Wearables" panel gear menu after initialization of mWearableItemsList and mInventoryItemsPanel. -	mAddWearablesGearMenu = LLAddWearablesGearMenu::create(mWearableItemsList, mInventoryItemsPanel); -	mWearablesGearMenuBtn->setMenu(mAddWearablesGearMenu); - -	mGearMenu = LLPanelOutfitEditGearMenu::create(); -	mGearMenuBtn->setMenu(mGearMenu); - -	getChild<LLButton>(SAVE_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false)); -	getChild<LLButton>(SAVE_AS_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true)); - -	onOutfitChanging(gAgentWearables.isCOFChangeInProgress()); -	return true; -} - -// virtual -void LLPanelOutfitEdit::onOpen(const LLSD& key) -{ -	if (!mInitialized) -	{ -		// *TODO: this method is called even panel is not visible to user because its parent layout panel is hidden. -		// So, we can defer initializing a bit. -		mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mListViewItemTypes[LVIT_ALL]->collector); -		displayCurrentOutfit(); -		mInitialized = true; -	} -} - -void LLPanelOutfitEdit::moveWearable(bool closer_to_body) -{ -	LLUUID item_id = mCOFWearables->getSelectedUUID(); -	if (item_id.isNull()) return; -	 -	LLViewerInventoryItem* wearable_to_move = gInventory.getItem(item_id); -	LLAppearanceMgr::getInstance()->moveWearable(wearable_to_move, closer_to_body); -} - -void LLPanelOutfitEdit::toggleAddWearablesPanel() -{ -	bool current_visibility = mAddWearablesPanel->getVisible(); -	showAddWearablesPanel(!current_visibility); -} - -void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables) -{ -	mAddWearablesPanel->setVisible(show_add_wearables); -	 -	getChild<LLUICtrl>("show_add_wearables_btn")->setValue(show_add_wearables); - -	updateFiltersVisibility(); -	getChildView("filter_button")->setVisible( show_add_wearables); - -	//search filter should be disabled -	if (!show_add_wearables) -	{ -		getChild<LLUICtrl>("filter_button")->setValue(false); - -		mFolderViewFilterCmbBox->setVisible(false); -		mListViewFilterCmbBox->setVisible(false); - -		showWearablesFilter(); - -		/* -		 * By default AT_CLOTHING are sorted by (in in MY OUTFITS): -		 *  - by type (types order determined in LLWearableType::EType) -		 *  - each LLWearableType::EType by outer layer on top -		 * -		 * In Add More panel AT_CLOTHING should be sorted in a such way: -		 *  - by type (types order determined in LLWearableType::EType) -		 *  - each LLWearableType::EType by name (EXT-8205) -		*/ -		mWearableItemsList->setSortOrder(LLWearableItemsList::E_SORT_BY_TYPE_NAME); - -		// Reset mWearableItemsList position to top. See EXT-8180. -		mWearableItemsList->goToTop(); -	} -	else -	{ -		mWearableListManager->populateIfNeeded(); -	} - -	//switching button bars -	getChildView("no_add_wearables_button_bar")->setVisible( !show_add_wearables); -	getChildView("add_wearables_button_bar")->setVisible( show_add_wearables); -} - -void LLPanelOutfitEdit::showWearablesFilter() -{ -	bool filter_visible = getChild<LLUICtrl>("filter_button")->getValue(); - -	getChildView("filter_panel")->setVisible( filter_visible); - -	if(!filter_visible) -	{ -		mSearchFilter->clear(); -		onSearchEdit(LLStringUtil::null); -	} -	else -	{ -		mSearchFilter->setFocus(true); -	} -} - -void LLPanelOutfitEdit::showWearablesListView() -{ -	if(switchPanels(mInventoryItemsPanel, mWearablesListViewPanel)) -	{ -		updateWearablesPanelVerbButtons(); -		updateFiltersVisibility(); -		mWearableListManager->populateIfNeeded(); -	} -	mListViewBtn->setToggleState(true); -} - -void LLPanelOutfitEdit::showWearablesFolderView() -{ -	if(switchPanels(mWearablesListViewPanel, mInventoryItemsPanel)) -	{ -		updateWearablesPanelVerbButtons(); -		updateFiltersVisibility(); -	} -	mFolderViewBtn->setToggleState(true); -} - -void LLPanelOutfitEdit::updateFiltersVisibility() -{ -	mListViewFilterCmbBox->setVisible(mWearablesListViewPanel->getVisible()); -	mFolderViewFilterCmbBox->setVisible(mInventoryItemsPanel->getVisible()); -} - -void LLPanelOutfitEdit::onFolderViewFilterCommitted(LLUICtrl* ctrl) -{ -	S32 curr_filter_type = mFolderViewFilterCmbBox->getCurrentIndex(); -	if (curr_filter_type < 0) return; - -	mInventoryItemsPanel->setFilterTypes(mFolderViewItemTypes[curr_filter_type].inventoryMask); - -	mSavedFolderState->setApply(true); -	mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); -	 -	LLOpenFoldersWithSelection opener; -	mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener); -	mInventoryItemsPanel->getRootFolder()->scrollToShowSelection(); - -    if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) -    { -        llassert(false); // this should have been done on startup -        LLInventoryModelBackgroundFetch::instance().start(); -    } -} - -void LLPanelOutfitEdit::onListViewFilterCommitted(LLUICtrl* ctrl) -{ -	S32 curr_filter_type = mListViewFilterCmbBox->getCurrentIndex(); -	if (curr_filter_type < 0) return; - -	if (curr_filter_type >= LVIT_SHAPE) -	{ -		mWearableItemsList->setMenuWearableType(LLWearableType::EType(curr_filter_type - LVIT_SHAPE)); -	} -	mWearableListManager->setFilterCollector(mListViewItemTypes[curr_filter_type]->collector); -} - -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); -		mWearableItemsList->setFilterSubString(LLStringUtil::null, true); -		// re-open folders that were initially open -		mSavedFolderState->setApply(true); -		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); -		LLOpenFoldersWithSelection opener; -		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener); -		mInventoryItemsPanel->getRootFolder()->scrollToShowSelection(); -	} - -    if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) -    { -        llassert(false); // this should have been done on startup -        LLInventoryModelBackgroundFetch::instance().start(); -    } -	 -	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->getFilterSubString().empty()) -	{ -		mSavedFolderState->setApply(false); -		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); -	} -	 -	// set new filter string -	mInventoryItemsPanel->setFilterSubString(mSearchString); -	mWearableItemsList->setFilterSubString(mSearchString, true); -} - -void LLPanelOutfitEdit::onPlusBtnClicked(void) -{ -	uuid_vec_t selected_items; -	getSelectedItemsUUID(selected_items); - -	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; -	 -	for(uuid_vec_t::iterator iter = selected_items.begin(); iter != selected_items.end(); iter++) -	{ -		LLUUID selected_id = *iter; -		if (!selected_id.isNull()) -		{ -			//replacing instead of adding the item -			LLAppearanceMgr::getInstance()->wearItemOnAvatar(selected_id, false, true, link_waiter); -		} -	} -} - -void LLPanelOutfitEdit::onVisibilityChanged(const LLSD &in_visible_chain) -{ -	showAddWearablesPanel(false); -	mWearableItemsList->resetSelection(); -	mInventoryItemsPanel->clearSelection(); - -	if (in_visible_chain.asBoolean()) -	{ -		update(); -	} -	else -	{ -		mWearableListManager->holdProgress(); //list population restarts with visibility -	} -} - -void LLPanelOutfitEdit::onAddWearableClicked(void) -{ -	LLPanelDummyClothingListItem* item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem()); - -	if(item) -	{ -		showFilteredWearablesListView(item->getWearableType()); -	} -} - -void LLPanelOutfitEdit::onReplaceMenuItemClicked(LLUUID selected_item_id) -{ -	LLViewerInventoryItem* item = gInventory.getLinkedItem(selected_item_id); - -	if (item) -	{ -		showFilteredWearablesListView(item->getWearableType()); -	} -} - -void LLPanelOutfitEdit::onShopButtonClicked() -{ -	static LLShopURLDispatcher url_resolver; - -	// will contain the resultant URL -	std::string url; - -	if (isAgentAvatarValid()) -	{ -		// try to get wearable type from 'Add More' panel first (EXT-7639) -		selection_info_t selection_info = getAddMorePanelSelectionType(); - -		LLWearableType::EType type = selection_info.first; - -		if (selection_info.second > 1) -		{ -			// the second argument is not important in this case: generic market place will be opened -			url = url_resolver.resolveURL(LLWearableType::WT_NONE, SEX_FEMALE); -		} -		else -		{ -		if (type == LLWearableType::WT_NONE) -		{ -			type = getCOFWearablesSelectionType(); -		} - -		ESex sex = gAgentAvatarp->getSex(); - -		// WT_INVALID comes for attachments -		if (type != LLWearableType::WT_INVALID && type != LLWearableType::WT_NONE) -		{ -			url = url_resolver.resolveURL(type, sex); -		} - -		if (url.empty()) -		{ -				url = url_resolver.resolveURL( -						mCOFWearables->getExpandedAccordionAssetType(), sex); -			} -		} -	} -	else -	{ -		LL_WARNS() << "Agent avatar is invalid" << LL_ENDL; - -		// the second argument is not important in this case: generic market place will be opened -		url = url_resolver.resolveURL(LLWearableType::WT_NONE, SEX_FEMALE); -	} - -	LLWeb::loadURL(url); -} - -LLWearableType::EType LLPanelOutfitEdit::getCOFWearablesSelectionType() const -{ -	std::vector<LLPanel*> selected_items; -	LLWearableType::EType type = LLWearableType::WT_NONE; - -	mCOFWearables->getSelectedItems(selected_items); - -	if (selected_items.size() == 1) -	{ -		LLPanel* item = selected_items.front(); - -		// LLPanelDummyClothingListItem is lower then LLPanelInventoryListItemBase in hierarchy tree -		if (LLPanelDummyClothingListItem* dummy_item = dynamic_cast<LLPanelDummyClothingListItem*>(item)) -		{ -			type = dummy_item->getWearableType(); -		} -		else if (LLPanelInventoryListItemBase* real_item = dynamic_cast<LLPanelInventoryListItemBase*>(item)) -		{ -			type = real_item->getWearableType(); -		} -	} - -	return type; -} - -LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionType() const -{ -	selection_info_t result = std::make_pair(LLWearableType::WT_NONE, 0); - -	if (mAddWearablesPanel != NULL && mAddWearablesPanel->getVisible()) -	{ -		if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible()) -		{ -			std::set<LLFolderViewItem*> selected_items =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); - -			result.second = selected_items.size(); - -			if (result.second == 1) -			{ -				result.first = getWearableTypeByItemUUID(static_cast<LLFolderViewModelItemInventory*>((*selected_items.begin())->getViewModelItem())->getUUID()); -			} -		} -		else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) -		{ -			std::vector<LLUUID> selected_uuids; -			mWearableItemsList->getSelectedUUIDs(selected_uuids); - -			result.second = selected_uuids.size(); - -			if (result.second == 1) -			{ -				result.first = getWearableTypeByItemUUID(selected_uuids.front()); -			} -		} -	} - -	return result; -} - -LLWearableType::EType LLPanelOutfitEdit::getWearableTypeByItemUUID(const LLUUID& item_uuid) const -{ -	LLViewerInventoryItem* item = gInventory.getLinkedItem(item_uuid); -	return (item != NULL) ? item->getWearableType() : LLWearableType::WT_NONE; -} - -void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void) -{ -	LLUUID id_to_remove = mCOFWearables->getSelectedUUID(); -	LLWearableType::EType type = getWearableTypeByItemUUID(id_to_remove); -	 -	LLAppearanceMgr::getInstance()->removeItemFromAvatar(id_to_remove); - -	if (!mCOFWearables->getSelectedItem()) -	{ -		mCOFWearables->selectClothing(type); -	} -} - - -void LLPanelOutfitEdit::onEditWearableClicked(void) -{ -	LLUUID selected_item_id = mCOFWearables->getSelectedUUID(); -	if (selected_item_id.notNull()) -	{ -		gAgentWearables.editWearable(selected_item_id); -	} -} - -void LLPanelOutfitEdit::updatePlusButton() -{ -	uuid_vec_t selected_items; -	getSelectedItemsUUID(selected_items); -	if (selected_items.empty()) -	{ -		mPlusBtn->setEnabled(false); -		return; -	} - -	// If any of the selected items are not wearable (due to already being worn OR being of the wrong type), disable the add button. -	uuid_vec_t::iterator unwearable_item = std::find_if(selected_items.begin(), selected_items.end(), !boost::bind(&get_can_item_be_worn, _1)); -	bool can_add = ( unwearable_item == selected_items.end() ); - -	mPlusBtn->setEnabled(can_add); - -	LLViewerInventoryItem* first_item(gInventory.getItem(selected_items.front())); - -	if (can_add &&  -		first_item && -		selected_items.size() == 1 &&  -		first_item->getType() == LLAssetType::AT_BODYPART) -	{ -		mPlusBtn->setToolTip(getString("replace_body_part")); -	} -	else -	{ -		mPlusBtn->setToolTip(LLStringUtil::null); -	} - -	/* 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::applyFolderViewFilter(EFolderViewItemType type) -{ -	mFolderViewFilterCmbBox->setCurrentByIndex(type); -	mFolderViewFilterCmbBox->onCommit(); -} - -void LLPanelOutfitEdit::applyListViewFilter(EListViewItemType type) -{ -	mListViewFilterCmbBox->setCurrentByIndex(type); -	mListViewFilterCmbBox->onCommit(); -} - -void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) -{ -	if (!mAddWearablesPanel->getVisible()) return; -	 -	uuid_vec_t ids; -	mCOFWearables->getSelectedUUIDs(ids); - -	bool nothing_selected = ids.empty(); -	bool one_selected = ids.size() == 1; -	bool more_than_one_selected = ids.size() > 1; -	bool is_dummy_item = (ids.size() && dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem())); - -	// selected, expanded accordion tabs and selection in flat list view determine filtering when no item is selected in COF -	// selection in flat list view participates in determining filtering because of EXT-7963 -	// So the priority of criterions in is: -	//                   1. Selected accordion tab            |  IF (any accordion selected) -	//                                                        |     filter_type = selected_accordion_type -	//                   2. Selected item in flat list view   |  ELSEIF (any item in flat list view selected) -	//                                                        |     filter_type = selected_item_type -	//                   3. Expanded accordion tab            |  ELSEIF (any accordion expanded) -	//                                                        |      filter_type = expanded accordion_type -	if (nothing_selected) -	{ -		if (mInventoryItemsPanel->getVisible()) -		{ -			return; -		} -		showWearablesListView(); - -		//selected accordion tab is more priority than expanded tab -		//and selected item in flat list view of 'Add more' panel when -		//determining filtering -		LLAssetType::EType type = mCOFWearables->getSelectedAccordionAssetType(); -		if (type == LLAssetType::AT_NONE) -		{ //no accordion selected - -			// when no accordion selected then selected item from flat list view -			// has more priority than expanded when determining filtering -			LLUUID selected_item_id = mWearableItemsList->getSelectedUUID(); -			LLViewerInventoryItem* item = gInventory.getLinkedItem(selected_item_id); -			if(item) -		{ -				showFilteredWearablesListView(item->getWearableType()); -				return; -			} - -			// when no accordion selected and no selected items in flat list view -			// determine filtering according to expanded accordion -			type = mCOFWearables->getExpandedAccordionAssetType(); -		} - -		switch (type) -		{ -		case LLAssetType::AT_OBJECT: -			applyListViewFilter(LVIT_ATTACHMENT); -			break; -		case LLAssetType::AT_BODYPART: -			applyListViewFilter(LVIT_BODYPART); -			break; -		case LLAssetType::AT_CLOTHING: -		default: -			applyListViewFilter(LVIT_CLOTHING); -			break; -		} - -		return; -	} - -	//resetting selection if more than one item is selected -	if (more_than_one_selected) -	{ -		if (mInventoryItemsPanel->getVisible()) -		{ -			applyFolderViewFilter(FVIT_ALL); -			return; -		} - -		showWearablesListView(); -		applyListViewFilter(LVIT_ALL); -		return; -	} - - -	//filter wearables by a type represented by a dummy item -	if (one_selected && is_dummy_item) -	{ -		if (mInventoryItemsPanel->getVisible()) -		{ -			applyFolderViewFilter(FVIT_WEARABLE); -			return; -		} - -		onAddWearableClicked(); -		return; -	} - -	LLViewerInventoryItem* item = gInventory.getItem(ids[0]); -	if (!item && ids[0].notNull()) -	{ -		if (mInventoryItemsPanel->getVisible()) -		{ -			applyFolderViewFilter(FVIT_ALL); -			return; -		} -		//Inventory misses an item with non-zero id -		showWearablesListView(); -		applyListViewFilter(LVIT_ALL); -		return; -	} - -	if (item && one_selected && !is_dummy_item) -	{ -		if (item->isWearableType()) -		{ -			if (mInventoryItemsPanel->getVisible()) -			{ -				applyFolderViewFilter(FVIT_WEARABLE); -				return; -			} -			//single clothing or bodypart item is selected -			showFilteredWearablesListView(item->getWearableType()); -			return; -		} -		else -		{ -			if (mInventoryItemsPanel->getVisible()) -			{ -				applyFolderViewFilter(FVIT_ATTACHMENT); -				return; -			} -			//attachment is selected -			showWearablesListView(); -			applyListViewFilter(LVIT_ATTACHMENT); -			return; -		} -	} - -} - - - -void LLPanelOutfitEdit::update() -{ -	mCOFWearables->refresh(); - -	updateVerbs(); -} - -bool LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, -										  EDragAndDropType cargo_type, -										  void* cargo_data, -										  EAcceptance* accept, -										  std::string& tooltip_msg) -{ -	if (cargo_data == NULL) -	{ -		LL_WARNS() << "cargo_data is NULL" << LL_ENDL; -		return true; -	} - -	switch (cargo_type) -	{ -	case DAD_BODYPART: -	case DAD_CLOTHING: -	case DAD_OBJECT: -	case DAD_LINK: -		*accept = ACCEPT_YES_MULTI; -		break; -	default: -		*accept = ACCEPT_NO; -	} - -	if (drop) -	{ -		LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data); - -		if (LLAssetType::lookupIsAssetIDKnowable(item->getType())) -		{ -			mCOFDragAndDropObserver->watchAsset(item->getAssetUUID()); - -			/* -			 * Adding request to wear item. If the item is a link, then getLinkedUUID() will -			 * return the ID of the linked item. Otherwise it will return the item's ID. The -			 * second argument is used to delay the appearance update until all dragged items -			 * are added to optimize user experience. -			 */ -			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID()); -		} -		else -		{ -			// if asset id is not available for the item we must wear it immediately (attachments only) -			LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), new LLUpdateAppearanceAndEditWearableOnDestroy(item->getUUID())); -		} -	} - -	return true; -} - -void LLPanelOutfitEdit::displayCurrentOutfit() -{ -	if (!getVisible()) -	{ -		setVisible(true); -	} - -	updateCurrentOutfitName(); - -	update(); -} - -void LLPanelOutfitEdit::updateCurrentOutfitName() -{ -	std::string current_outfit_name; -	if (LLAppearanceMgr::getInstance()->getBaseOutfitName(current_outfit_name)) -	{ -		mCurrentOutfitName->setText(current_outfit_name); -	} -	else -	{ -		mCurrentOutfitName->setText(getString("No Outfit")); -	} -} - -//private -void LLPanelOutfitEdit::updateVerbs() -{ -	bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty(); -	bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked(); -	bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull(); - -	getChildView(SAVE_BTN)->setEnabled(!outfit_locked && outfit_is_dirty); -	getChildView(REVERT_BTN)->setEnabled(outfit_is_dirty && has_baseoutfit); - -	mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing")); - -	updateCurrentOutfitName(); - -	//updating state of "Wear Item" button previously known as "Plus" button -	updatePlusButton(); -} - -bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel) -{ -	if(switch_from_panel && switch_to_panel && !switch_to_panel->getVisible()) -	{ -		switch_from_panel->setVisible(false); -		switch_to_panel->setVisible(true); -		return true; -	} -	return false; -} - -void LLPanelOutfitEdit::resetAccordionState() -{ -	if (mCOFWearables != NULL) -	{ -		mCOFWearables->expandDefaultAccordionTab(); -	} -	else -	{ -		LL_WARNS() << "mCOFWearables is NULL" << LL_ENDL; -	} -} - -void LLPanelOutfitEdit::onAddMoreButtonClicked() -{ -	toggleAddWearablesPanel(); -	filterWearablesBySelectedItem(); -} - -void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type) -{ -	showAddWearablesPanel(true); -	showWearablesListView(); - -	//e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE -	applyListViewFilter(static_cast<EListViewItemType>(LVIT_SHAPE + type)); -	mWearableItemsList->setMenuWearableType(type); -} - -static void update_status_widget_rect(LLView * widget, S32 right_border) -{ -	LLRect rect = widget->getRect(); -	rect.mRight = right_border; - -	widget->setShape(rect); -} - -void LLPanelOutfitEdit::onOutfitChanging(bool started) -{ -	static LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("edit_outfit_loading_indicator"); -	static LLView* status_panel = getChild<LLView>("outfit_name_and_status"); -	static S32 indicator_delta = status_panel->getRect().getWidth() - indicator->getRect().mLeft; - -	S32 delta = started ? indicator_delta : 0; -	S32 right_border = status_panel->getRect().getWidth() - delta; - -	if (mCurrentOutfitName) -		update_status_widget_rect(mCurrentOutfitName, right_border); -	if (mStatus) -		update_status_widget_rect(mStatus, right_border); - -	indicator->setVisible(started); -} - -void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id) -{ -	if (mInventoryItemsPanel->getVisible()) -	{ -		LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem(); -		if (!curr_item) return; - -		LLFolderViewModelItemInventory* listenerp  = static_cast<LLFolderViewModelItemInventory*>(curr_item->getViewModelItem()); -		if (!listenerp) return; - -		selected_id = listenerp->getUUID(); -	} -	else if (mWearablesListViewPanel->getVisible()) -	{ -		selected_id = mWearableItemsList->getSelectedUUID(); -	} -} - - -void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list) -{ -	void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back; -	if (mInventoryItemsPanel->getVisible()) -	{ -		std::set<LLFolderViewItem*> item_set =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); -		for (std::set<LLFolderViewItem*>::iterator it = item_set.begin(),    end_it = item_set.end(); -			it != end_it; -			++it) -		{ -			uuid_list.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); -		} -	} -	else if (mWearablesListViewPanel->getVisible()) -	{ -		std::vector<LLSD> item_set; -		mWearableItemsList->getSelectedValues(item_set); - -		std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, boost::bind(&LLSD::asUUID, _1 ))); -	} - -//	return selected_id; -} - -void LLPanelOutfitEdit::onCOFChanged() -{ -	//the panel is only updated when is visible to a user - -	// BAP - this check has to be removed because otherwise item name -	// changes made when the panel is not visible will not be -	// propagated to the panel. -	// if (!isInVisibleChain()) return; - -	update(); -} - -void LLPanelOutfitEdit::updateWearablesPanelVerbButtons() -{ -	if(mWearablesListViewPanel->getVisible()) -	{ -		mFolderViewBtn->setToggleState(false); -		mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign()); -		mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign()); -	} -	else if(mInventoryItemsPanel->getVisible()) -	{ -		mListViewBtn->setToggleState(false); -		mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign()); -		mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign()); -	} -} - -void LLPanelOutfitEdit::saveListSelection() -{ -	if(mWearablesListViewPanel->getVisible()) -	{ -		std::set<LLFolderViewItem*> selected_ids =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); - -		if(!selected_ids.size()) return; - -		for (std::set<LLFolderViewItem*>::const_iterator item_id =    selected_ids.begin(); item_id != selected_ids.end(); ++item_id) -		{ -			mWearableItemsList->selectItemByUUID(static_cast<LLFolderViewModelItemInventory*>((*item_id)->getViewModelItem())->getUUID(),    true); -		} -		mWearableItemsList->scrollToShowFirstSelectedItem(); -	} -	else if(mInventoryItemsPanel->getVisible()) -	{ -		std::vector<LLUUID> selected_ids; -		mWearableItemsList->getSelectedUUIDs(selected_ids); - -		if(!selected_ids.size()) return; - -		mInventoryItemsPanel->clearSelection(); -		LLFolderView* root = mInventoryItemsPanel->getRootFolder(); - -		if(!root) return; - -		for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) -		{ -			LLFolderViewItem* item = mInventoryItemsPanel->getItemByID(*item_id); -			if (!item) continue; - -			LLFolderViewFolder* parent = item->getParentFolder(); -			if(parent) -			{ -				parent->setOpenArrangeRecursively(true, LLFolderViewFolder::RECURSE_UP); -			} -			mInventoryItemsPanel->getRootFolder()->changeSelection(item, true); -		} -		mInventoryItemsPanel->getRootFolder()->scrollToShowSelection(); -	} -} - -void LLPanelOutfitEdit::saveOutfit(bool as_new) -{ -	LLPanelOutfitsInventory* panel_outfits_inventory = LLPanelOutfitsInventory::findInstance(); -	if (panel_outfits_inventory) -	{ -		panel_outfits_inventory->saveOutfit(as_new); -	} 	 -} - -// EOF +/**
 + * @file llpaneloutfitedit.cpp
 + * @brief Displays outfit edit information in Side Tray.
 + *
 + * $LicenseInfo:firstyear=2009&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, Linden Research, Inc.
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation;
 + * version 2.1 of the License only.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 + *
 + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 + * $/LicenseInfo$
 + */
 +
 +#include "llviewerprecompiledheaders.h"
 +
 +#include "llpaneloutfitedit.h"
 +
 +// *TODO: reorder includes to match the coding standard
 +#include "llagent.h"
 +#include "llagentcamera.h"
 +#include "llagentwearables.h"
 +#include "llappearancemgr.h"
 +#include "lloutfitobserver.h"
 +#include "llcofwearables.h"
 +#include "llfilteredwearablelist.h"
 +#include "llfolderview.h"
 +#include "llinventory.h"
 +#include "llinventoryitemslist.h"
 +#include "llviewercontrol.h"
 +#include "llui.h"
 +#include "llfloater.h"
 +#include "llfloaterreg.h"
 +#include "llinventoryfunctions.h"
 +#include "llinventorypanel.h"
 +#include "llviewermenu.h"
 +#include "llviewerwindow.h"
 +#include "llviewerinventory.h"
 +#include "llbutton.h"
 +#include "llcombobox.h"
 +#include "llfiltereditor.h"
 +#include "llinventorybridge.h"
 +#include "llinventorymodel.h"
 +#include "llinventorymodelbackgroundfetch.h"
 +#include "llloadingindicator.h"
 +#include "llmenubutton.h"
 +#include "llpaneloutfitsinventory.h"
 +#include "lluiconstants.h"
 +#include "llscrolllistctrl.h"
 +#include "lltextbox.h"
 +#include "lltoggleablemenu.h"
 +#include "lltrans.h"
 +#include "lluictrlfactory.h"
 +#include "llsdutil.h"
 +#include "llsidepanelappearance.h"
 +#include "lltoggleablemenu.h"
 +#include "llvoavatarself.h"
 +#include "llwearablelist.h"
 +#include "llwearableitemslist.h"
 +#include "llwearabletype.h"
 +#include "llweb.h"
 +
 +static LLPanelInjector<LLPanelOutfitEdit> t_outfit_edit("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;
 +
 +static const std::string REVERT_BTN("revert_btn");
 +static const std::string SAVE_AS_BTN("save_as_btn");
 +static const std::string SAVE_BTN("save_btn");
 +
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// LLShopURLDispatcher
 +///////////////////////////////////////////////////////////////////////////////
 +
 +class LLShopURLDispatcher
 +{
 +public:
 +    std::string resolveURL(LLWearableType::EType wearable_type, ESex sex);
 +    std::string resolveURL(LLAssetType::EType asset_type, ESex sex);
 +};
 +
 +std::string LLShopURLDispatcher::resolveURL(LLWearableType::EType wearable_type, ESex sex)
 +{
 +    const std::string prefix = "MarketplaceURL";
 +    const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female";
 +    const std::string type_str = LLWearableType::getInstance()->getTypeName(wearable_type);
 +
 +    std::string setting_name = prefix;
 +
 +    switch (wearable_type)
 +    {
 +    case LLWearableType::WT_ALPHA:
 +    case LLWearableType::WT_NONE:
 +    case LLWearableType::WT_INVALID:    // just in case, this shouldn't happen
 +    case LLWearableType::WT_COUNT:      // just in case, this shouldn't happen
 +        break;
 +
 +    default:
 +        setting_name += '_';
 +        setting_name += type_str;
 +        setting_name += sex_str;
 +        break;
 +    }
 +
 +    return gSavedSettings.getString(setting_name);
 +}
 +
 +std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex sex)
 +{
 +    const std::string prefix = "MarketplaceURL";
 +    const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female";
 +    const std::string type_str = LLAssetType::lookup(asset_type);
 +
 +    std::string setting_name = prefix;
 +
 +    switch (asset_type)
 +    {
 +    case LLAssetType::AT_CLOTHING:
 +    case LLAssetType::AT_OBJECT:
 +    case LLAssetType::AT_BODYPART:
 +        setting_name += '_';
 +        setting_name += type_str;
 +        setting_name += sex_str;
 +        break;
 +
 +    // to suppress warnings
 +    default:
 +        break;
 +    }
 +
 +    return gSavedSettings.getString(setting_name);
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// LLPanelOutfitEditGearMenu
 +///////////////////////////////////////////////////////////////////////////////
 +
 +class LLPanelOutfitEditGearMenu
 +{
 +public:
 +    static LLToggleableMenu* create()
 +    {
 +        LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 +
 +        registrar.add("Wearable.Create", boost::bind(onCreate, _2));
 +
 +        llassert(LLMenuGL::sMenuContainer != NULL);
 +        LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
 +            "menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 +        llassert(menu);
 +        if (menu)
 +        {
 +            populateCreateWearableSubmenus(menu);
 +        }
 +
 +        return menu;
 +    }
 +
 +private:
 +    static void onCreate(const LLSD& param)
 +    {
 +        LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(param.asString());
 +        if (type == LLWearableType::WT_NONE)
 +        {
 +            LL_WARNS() << "Invalid wearable type" << LL_ENDL;
 +            return;
 +        }
 +
 +        LLAgentWearables::createWearable(type, true);
 +    }
 +
 +    // Populate the menu with items like "New Skin", "New Pants", etc.
 +    static void populateCreateWearableSubmenus(LLMenuGL* menu)
 +    {
 +        LLView* menu_clothes    = gMenuHolder->getChildView("COF.Gear.New_Clothes", false);
 +        LLView* menu_bp         = gMenuHolder->getChildView("COF.Gear.New_Body_Parts", false);
 +        LLWearableType * wearable_type_inst = LLWearableType::getInstance();
 +
 +        for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i)
 +        {
 +            LLWearableType::EType type = (LLWearableType::EType) i;
 +            const std::string& type_name = wearable_type_inst->getTypeName(type);
 +
 +            LLMenuItemCallGL::Params p;
 +            p.name = type_name;
 +            p.label = LLTrans::getString(wearable_type_inst->getTypeDefaultNewName(type));
 +            p.on_click.function_name = "Wearable.Create";
 +            p.on_click.parameter = LLSD(type_name);
 +
 +            LLView* parent = wearable_type_inst->getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp;
 +            LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
 +        }
 +    }
 +};
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// LLAddWearablesGearMenu
 +///////////////////////////////////////////////////////////////////////////////
 +
 +class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu>
 +{
 +public:
 +    static LLToggleableMenu* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel)
 +    {
 +        LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 +        LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
 +
 +        llassert(flat_list);
 +        llassert(inventory_panel);
 +
 +        LLHandle<LLView> flat_list_handle = flat_list->getHandle();
 +        LLHandle<LLPanel> inventory_panel_handle = inventory_panel->getHandle();
 +
 +        registrar.add("AddWearable.Gear.Sort", boost::bind(onSort, flat_list_handle, inventory_panel_handle, _2));
 +        enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2));
 +        enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2));
 +
 +        llassert(LLMenuGL::sMenuContainer != NULL);
 +        LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
 +            "menu_add_wearable_gear.xml",
 +            LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
 +
 +        return menu;
 +    }
 +
 +private:
 +    static void onSort(LLHandle<LLView> flat_list_handle,
 +                       LLHandle<LLPanel> inventory_panel_handle,
 +                       LLSD::String sort_order_str)
 +    {
 +        if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return;
 +
 +        LLWearableItemsList* flat_list = dynamic_cast<LLWearableItemsList*>(flat_list_handle.get());
 +        LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get());
 +
 +        if (!flat_list || !inventory_panel) return;
 +
 +        LLWearableItemsList::ESortOrder sort_order;
 +
 +        if ("by_most_recent" == sort_order_str)
 +        {
 +            sort_order = LLWearableItemsList::E_SORT_BY_MOST_RECENT;
 +        }
 +        else if ("by_name" == sort_order_str)
 +        {
 +            sort_order = LLWearableItemsList::E_SORT_BY_NAME;
 +        }
 +        else if ("by_type" == sort_order_str)
 +        {
 +            sort_order = LLWearableItemsList::E_SORT_BY_TYPE_NAME;
 +        }
 +        else
 +        {
 +            LL_WARNS() << "Unrecognized sort order action" << LL_ENDL;
 +            return;
 +        }
 +
 +        if (inventory_panel->getVisible())
 +        {
 +            inventory_panel->getFolderViewModel()->setSorter(sort_order);
 +        }
 +        else
 +        {
 +            flat_list->setSortOrder(sort_order);
 +        }
 +    }
 +
 +    static bool onCheck(LLHandle<LLView> flat_list_handle,
 +                        LLHandle<LLPanel> inventory_panel_handle,
 +                        LLSD::String sort_order_str)
 +    {
 +        if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return false;
 +
 +        LLWearableItemsList* flat_list = dynamic_cast<LLWearableItemsList*>(flat_list_handle.get());
 +        LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get());
 +
 +        if (!inventory_panel || !flat_list) return false;
 +
 +        // Inventory panel uses its own sort order independent from
 +        // flat list view so this flag is used to distinguish between
 +        // currently visible "tree" or "flat" representation of inventory.
 +        bool inventory_tree_visible = inventory_panel->getVisible();
 +
 +        if (inventory_tree_visible)
 +        {
 +            U32 sort_order = inventory_panel->getSortOrder();
 +
 +            if ("by_most_recent" == sort_order_str)
 +            {
 +                return LLWearableItemsList::E_SORT_BY_MOST_RECENT & sort_order;
 +            }
 +            else if ("by_name" == sort_order_str)
 +            {
 +                // If inventory panel is not sorted by date then it is sorted by name.
 +                return LLWearableItemsList::E_SORT_BY_MOST_RECENT & ~sort_order;
 +            }
 +            LL_WARNS() << "Unrecognized inventory panel sort order" << LL_ENDL;
 +        }
 +        else
 +        {
 +            LLWearableItemsList::ESortOrder sort_order = flat_list->getSortOrder();
 +
 +            if ("by_most_recent" == sort_order_str)
 +            {
 +                return LLWearableItemsList::E_SORT_BY_MOST_RECENT == sort_order;
 +            }
 +            else if ("by_name" == sort_order_str)
 +            {
 +                return LLWearableItemsList::E_SORT_BY_NAME == sort_order;
 +            }
 +            else if ("by_type" == sort_order_str)
 +            {
 +                return LLWearableItemsList::E_SORT_BY_TYPE_NAME == sort_order;
 +            }
 +            LL_WARNS() << "Unrecognized wearable list sort order" << LL_ENDL;
 +        }
 +        return false;
 +    }
 +
 +    static bool onVisible(LLHandle<LLPanel> inventory_panel_handle,
 +                          LLSD::String sort_order_str)
 +    {
 +        if (inventory_panel_handle.isDead()) return false;
 +
 +        LLInventoryPanel* inventory_panel = dynamic_cast<LLInventoryPanel*>(inventory_panel_handle.get());
 +
 +        // Enable sorting by type only for the flat list of items
 +        // because inventory panel doesn't support this kind of sorting.
 +        return ( "by_type" == sort_order_str )
 +                &&  ( !inventory_panel || !inventory_panel->getVisible() );
 +    }
 +};
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// LLCOFDragAndDropObserver
 +///////////////////////////////////////////////////////////////////////////////
 +
 +class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver
 +{
 +public:
 +    LLCOFDragAndDropObserver(LLInventoryModel* model);
 +
 +    virtual ~LLCOFDragAndDropObserver();
 +
 +    virtual void done();
 +
 +private:
 +    LLInventoryModel* mModel;
 +};
 +
 +inline LLCOFDragAndDropObserver::LLCOFDragAndDropObserver(LLInventoryModel* model):
 +        mModel(model)
 +{
 +    if (model != NULL)
 +    {
 +        model->addObserver(this);
 +    }
 +}
 +
 +inline LLCOFDragAndDropObserver::~LLCOFDragAndDropObserver()
 +{
 +    if (mModel != NULL && mModel->containsObserver(this))
 +    {
 +        mModel->removeObserver(this);
 +    }
 +}
 +
 +void LLCOFDragAndDropObserver::done()
 +{
 +    LLAppearanceMgr::instance().updateAppearanceFromCOF();
 +}
 +
 +///////////////////////////////////////////////////////////////////////////////
 +// LLPanelOutfitEdit
 +///////////////////////////////////////////////////////////////////////////////
 +
 +LLPanelOutfitEdit::LLPanelOutfitEdit()
 +:   LLPanel(),
 +    mSearchFilter(NULL),
 +    mCOFWearables(NULL),
 +    mInventoryItemsPanel(NULL),
 +    mGearMenu(NULL),
 +    mAddWearablesGearMenu(NULL),
 +    mCOFDragAndDropObserver(NULL),
 +    mInitialized(false),
 +    mAddWearablesPanel(NULL),
 +    mFolderViewFilterCmbBox(NULL),
 +    mListViewFilterCmbBox(NULL),
 +    mWearableListManager(NULL),
 +    mPlusBtn(NULL),
 +    mWearablesGearMenuBtn(NULL),
 +    mGearMenuBtn(NULL)
 +{
 +    mSavedFolderState = new LLSaveFolderState();
 +    mSavedFolderState->setApply(false);
 +
 +
 +    LLOutfitObserver& observer = LLOutfitObserver::instance();
 +    observer.addBOFReplacedCallback(boost::bind(&LLPanelOutfitEdit::updateCurrentOutfitName, this));
 +    observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this));
 +    observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this));
 +    observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitEdit::onCOFChanged, this));
 +
 +    gAgentWearables.addLoadingStartedCallback(boost::bind(&LLPanelOutfitEdit::onOutfitChanging, this, true));
 +    gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitEdit::onOutfitChanging, this, false));
 +
 +    mFolderViewItemTypes.reserve(NUM_FOLDER_VIEW_ITEM_TYPES);
 +    for (U32 i = 0; i < NUM_FOLDER_VIEW_ITEM_TYPES; i++)
 +    {
 +        mFolderViewItemTypes.push_back(LLLookItemType());
 +    }
 +
 +}
 +
 +LLPanelOutfitEdit::~LLPanelOutfitEdit()
 +{
 +    delete mWearableListManager;
 +    delete mSavedFolderState;
 +
 +    delete mCOFDragAndDropObserver;
 +
 +    while (!mListViewItemTypes.empty()) {
 +        delete mListViewItemTypes.back();
 +        mListViewItemTypes.pop_back();
 +    }
 +}
 +
 +bool LLPanelOutfitEdit::postBuild()
 +{
 +    // gInventory.isInventoryUsable() no longer needs to be tested per Richard's fix for race conditions between inventory and panels
 +
 +    mFolderViewItemTypes[FVIT_ALL] = LLLookItemType(getString("Filter.All"), ALL_ITEMS_MASK);
 +    mFolderViewItemTypes[FVIT_WEARABLE] = LLLookItemType(getString("Filter.Clothes/Body"), WEARABLE_MASK);
 +    mFolderViewItemTypes[FVIT_ATTACHMENT] = LLLookItemType(getString("Filter.Objects"), ATTACHMENT_MASK);
 +
 +    //order is important, see EListViewItemType for order information
 +    mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.All"), new LLFindNonLinksByMask(ALL_ITEMS_MASK)));
 +    mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Clothing"), new LLIsTypeActual(LLAssetType::AT_CLOTHING)));
 +    mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Bodyparts"), new LLIsTypeActual(LLAssetType::AT_BODYPART)));
 +    mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Objects"), new LLFindNonLinksByMask(ATTACHMENT_MASK)));;
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shape"), new LLFindActualWearablesOfType(LLWearableType::WT_SHAPE)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skin"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIN)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("hair"), new LLFindActualWearablesOfType(LLWearableType::WT_HAIR)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("eyes"), new LLFindActualWearablesOfType(LLWearableType::WT_EYES)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SHIRT)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("pants"), new LLFindActualWearablesOfType(LLWearableType::WT_PANTS)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shoes"), new LLFindActualWearablesOfType(LLWearableType::WT_SHOES)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("socks"), new LLFindActualWearablesOfType(LLWearableType::WT_SOCKS)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("jacket"), new LLFindActualWearablesOfType(LLWearableType::WT_JACKET)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("gloves"), new LLFindActualWearablesOfType(LLWearableType::WT_GLOVES)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("undershirt"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERSHIRT)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("underpants"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERPANTS)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIRT)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("alpha"), new LLFindActualWearablesOfType(LLWearableType::WT_ALPHA)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("tattoo"), new LLFindActualWearablesOfType(LLWearableType::WT_TATTOO)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("physics"), new LLFindActualWearablesOfType(LLWearableType::WT_PHYSICS)));
 +    mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("universal"), new LLFindActualWearablesOfType(LLWearableType::WT_UNIVERSAL)));
 +
 +    mCurrentOutfitName = getChild<LLTextBox>("curr_outfit_name");
 +    mStatus = getChild<LLTextBox>("status");
 +
 +    mFolderViewBtn = getChild<LLButton>("folder_view_btn");
 +    mListViewBtn = getChild<LLButton>("list_view_btn");
 +
 +    childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);
 +    childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL);
 +    childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);
 +    childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL);
 +    childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);
 +    childSetCommitCallback("shop_btn_1", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL);
 +    childSetCommitCallback("shop_btn_2", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL);
 +
 +    setVisibleCallback(boost::bind(&LLPanelOutfitEdit::onVisibilityChanged, this, _2));
 +
 +    mWearablesGearMenuBtn = getChild<LLMenuButton>("wearables_gear_menu_btn");
 +    mGearMenuBtn = getChild<LLMenuButton>("gear_menu_btn");
 +
 +    mCOFWearables = findChild<LLCOFWearables>("cof_wearables_list");
 +    mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, 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);
 +    mCOFWearables->getCOFCallbacks().mMoveWearableFurther = boost::bind(&LLPanelOutfitEdit::moveWearable, this, false);
 +
 +    mAddWearablesPanel = getChild<LLPanel>("add_wearables_panel");
 +
 +    mInventoryItemsPanel = getChild<LLInventoryPanel>("folder_view");
 +    mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK);
 +    mInventoryItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
 +    mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));
 +    mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));
 +
 +    mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel());
 +
 +    mFolderViewFilterCmbBox = getChild<LLComboBox>("folder_view_filter_combobox");
 +    mFolderViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onFolderViewFilterCommitted, this, _1));
 +    mFolderViewFilterCmbBox->removeall();
 +    for (U32 i = 0; i < mFolderViewItemTypes.size(); ++i)
 +    {
 +        mFolderViewFilterCmbBox->add(mFolderViewItemTypes[i].displayName);
 +    }
 +    mFolderViewFilterCmbBox->setCurrentByIndex(FVIT_ALL);
 +
 +    mListViewFilterCmbBox = getChild<LLComboBox>("list_view_filter_combobox");
 +    mListViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onListViewFilterCommitted, this, _1));
 +    mListViewFilterCmbBox->removeall();
 +    for (U32 i = 0; i < mListViewItemTypes.size(); ++i)
 +    {
 +        mListViewFilterCmbBox->add(mListViewItemTypes[i]->displayName);
 +    }
 +    mListViewFilterCmbBox->setCurrentByIndex(LVIT_ALL);
 +
 +    mSearchFilter = getChild<LLFilterEditor>("look_item_filter");
 +    mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2));
 +
 +    childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::onAddMoreButtonClicked, this));
 +
 +    mPlusBtn = getChild<LLButton>("plus_btn");
 +    mPlusBtn->setClickedCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this));
 +
 +    childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance()));
 +
 +    /*
 +     * By default AT_CLOTHING are sorted by (in in MY OUTFITS):
 +     *  - by type (types order determined in LLWearableType::EType)
 +     *  - each LLWearableType::EType by outer layer on top
 +     *
 +     * In Add More panel AT_CLOTHING should be sorted in a such way:
 +     *  - by type (types order determined in LLWearableType::EType)
 +     *  - each LLWearableType::EType by name (EXT-8205)
 +    */
 +    mWearableListViewItemsComparator = new LLWearableItemTypeNameComparator();
 +    mWearableListViewItemsComparator->setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANK_1, false, true);
 +
 +    mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel");
 +    mWearableItemsList = getChild<LLWearableItemsList>("list_view");
 +    mWearableItemsList->setCommitOnSelectionChange(true);
 +    mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));
 +    mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this));
 +
 +    mWearableItemsList->setComparator(mWearableListViewItemsComparator);
 +
 +    // Creating "Add Wearables" panel gear menu after initialization of mWearableItemsList and mInventoryItemsPanel.
 +    mAddWearablesGearMenu = LLAddWearablesGearMenu::create(mWearableItemsList, mInventoryItemsPanel);
 +    mWearablesGearMenuBtn->setMenu(mAddWearablesGearMenu);
 +
 +    mGearMenu = LLPanelOutfitEditGearMenu::create();
 +    mGearMenuBtn->setMenu(mGearMenu);
 +
 +    getChild<LLButton>(SAVE_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false));
 +    getChild<LLButton>(SAVE_AS_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true));
 +
 +    onOutfitChanging(gAgentWearables.isCOFChangeInProgress());
 +    return true;
 +}
 +
 +// virtual
 +void LLPanelOutfitEdit::onOpen(const LLSD& key)
 +{
 +    if (!mInitialized)
 +    {
 +        // *TODO: this method is called even panel is not visible to user because its parent layout panel is hidden.
 +        // So, we can defer initializing a bit.
 +        mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mListViewItemTypes[LVIT_ALL]->collector);
 +        displayCurrentOutfit();
 +        mInitialized = true;
 +    }
 +}
 +
 +void LLPanelOutfitEdit::moveWearable(bool closer_to_body)
 +{
 +    LLUUID item_id = mCOFWearables->getSelectedUUID();
 +    if (item_id.isNull()) return;
 +
 +    LLViewerInventoryItem* wearable_to_move = gInventory.getItem(item_id);
 +    LLAppearanceMgr::getInstance()->moveWearable(wearable_to_move, closer_to_body);
 +}
 +
 +void LLPanelOutfitEdit::toggleAddWearablesPanel()
 +{
 +    bool current_visibility = mAddWearablesPanel->getVisible();
 +    showAddWearablesPanel(!current_visibility);
 +}
 +
 +void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables)
 +{
 +    mAddWearablesPanel->setVisible(show_add_wearables);
 +
 +    getChild<LLUICtrl>("show_add_wearables_btn")->setValue(show_add_wearables);
 +
 +    updateFiltersVisibility();
 +    getChildView("filter_button")->setVisible( show_add_wearables);
 +
 +    //search filter should be disabled
 +    if (!show_add_wearables)
 +    {
 +        getChild<LLUICtrl>("filter_button")->setValue(false);
 +
 +        mFolderViewFilterCmbBox->setVisible(false);
 +        mListViewFilterCmbBox->setVisible(false);
 +
 +        showWearablesFilter();
 +
 +        /*
 +         * By default AT_CLOTHING are sorted by (in in MY OUTFITS):
 +         *  - by type (types order determined in LLWearableType::EType)
 +         *  - each LLWearableType::EType by outer layer on top
 +         *
 +         * In Add More panel AT_CLOTHING should be sorted in a such way:
 +         *  - by type (types order determined in LLWearableType::EType)
 +         *  - each LLWearableType::EType by name (EXT-8205)
 +        */
 +        mWearableItemsList->setSortOrder(LLWearableItemsList::E_SORT_BY_TYPE_NAME);
 +
 +        // Reset mWearableItemsList position to top. See EXT-8180.
 +        mWearableItemsList->goToTop();
 +    }
 +    else
 +    {
 +        mWearableListManager->populateIfNeeded();
 +    }
 +
 +    //switching button bars
 +    getChildView("no_add_wearables_button_bar")->setVisible( !show_add_wearables);
 +    getChildView("add_wearables_button_bar")->setVisible( show_add_wearables);
 +}
 +
 +void LLPanelOutfitEdit::showWearablesFilter()
 +{
 +    bool filter_visible = getChild<LLUICtrl>("filter_button")->getValue();
 +
 +    getChildView("filter_panel")->setVisible( filter_visible);
 +
 +    if(!filter_visible)
 +    {
 +        mSearchFilter->clear();
 +        onSearchEdit(LLStringUtil::null);
 +    }
 +    else
 +    {
 +        mSearchFilter->setFocus(true);
 +    }
 +}
 +
 +void LLPanelOutfitEdit::showWearablesListView()
 +{
 +    if(switchPanels(mInventoryItemsPanel, mWearablesListViewPanel))
 +    {
 +        updateWearablesPanelVerbButtons();
 +        updateFiltersVisibility();
 +        mWearableListManager->populateIfNeeded();
 +    }
 +    mListViewBtn->setToggleState(true);
 +}
 +
 +void LLPanelOutfitEdit::showWearablesFolderView()
 +{
 +    if(switchPanels(mWearablesListViewPanel, mInventoryItemsPanel))
 +    {
 +        updateWearablesPanelVerbButtons();
 +        updateFiltersVisibility();
 +    }
 +    mFolderViewBtn->setToggleState(true);
 +}
 +
 +void LLPanelOutfitEdit::updateFiltersVisibility()
 +{
 +    mListViewFilterCmbBox->setVisible(mWearablesListViewPanel->getVisible());
 +    mFolderViewFilterCmbBox->setVisible(mInventoryItemsPanel->getVisible());
 +}
 +
 +void LLPanelOutfitEdit::onFolderViewFilterCommitted(LLUICtrl* ctrl)
 +{
 +    S32 curr_filter_type = mFolderViewFilterCmbBox->getCurrentIndex();
 +    if (curr_filter_type < 0) return;
 +
 +    mInventoryItemsPanel->setFilterTypes(mFolderViewItemTypes[curr_filter_type].inventoryMask);
 +
 +    mSavedFolderState->setApply(true);
 +    mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
 +
 +    LLOpenFoldersWithSelection opener;
 +    mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener);
 +    mInventoryItemsPanel->getRootFolder()->scrollToShowSelection();
 +
 +    if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted())
 +    {
 +        llassert(false); // this should have been done on startup
 +        LLInventoryModelBackgroundFetch::instance().start();
 +    }
 +}
 +
 +void LLPanelOutfitEdit::onListViewFilterCommitted(LLUICtrl* ctrl)
 +{
 +    S32 curr_filter_type = mListViewFilterCmbBox->getCurrentIndex();
 +    if (curr_filter_type < 0) return;
 +
 +    if (curr_filter_type >= LVIT_SHAPE)
 +    {
 +        mWearableItemsList->setMenuWearableType(LLWearableType::EType(curr_filter_type - LVIT_SHAPE));
 +    }
 +    mWearableListManager->setFilterCollector(mListViewItemTypes[curr_filter_type]->collector);
 +}
 +
 +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);
 +        mWearableItemsList->setFilterSubString(LLStringUtil::null, true);
 +        // re-open folders that were initially open
 +        mSavedFolderState->setApply(true);
 +        mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
 +        LLOpenFoldersWithSelection opener;
 +        mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(opener);
 +        mInventoryItemsPanel->getRootFolder()->scrollToShowSelection();
 +    }
 +
 +    if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted())
 +    {
 +        llassert(false); // this should have been done on startup
 +        LLInventoryModelBackgroundFetch::instance().start();
 +    }
 +
 +    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->getFilterSubString().empty())
 +    {
 +        mSavedFolderState->setApply(false);
 +        mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
 +    }
 +
 +    // set new filter string
 +    mInventoryItemsPanel->setFilterSubString(mSearchString);
 +    mWearableItemsList->setFilterSubString(mSearchString, true);
 +}
 +
 +void LLPanelOutfitEdit::onPlusBtnClicked(void)
 +{
 +    uuid_vec_t selected_items;
 +    getSelectedItemsUUID(selected_items);
 +
 +    LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
 +
 +    for(uuid_vec_t::iterator iter = selected_items.begin(); iter != selected_items.end(); iter++)
 +    {
 +        LLUUID selected_id = *iter;
 +        if (!selected_id.isNull())
 +        {
 +            //replacing instead of adding the item
 +            LLAppearanceMgr::getInstance()->wearItemOnAvatar(selected_id, false, true, link_waiter);
 +        }
 +    }
 +}
 +
 +void LLPanelOutfitEdit::onVisibilityChanged(const LLSD &in_visible_chain)
 +{
 +    showAddWearablesPanel(false);
 +    mWearableItemsList->resetSelection();
 +    mInventoryItemsPanel->clearSelection();
 +
 +    if (in_visible_chain.asBoolean())
 +    {
 +        update();
 +    }
 +    else
 +    {
 +        mWearableListManager->holdProgress(); //list population restarts with visibility
 +    }
 +}
 +
 +void LLPanelOutfitEdit::onAddWearableClicked(void)
 +{
 +    LLPanelDummyClothingListItem* item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem());
 +
 +    if(item)
 +    {
 +        showFilteredWearablesListView(item->getWearableType());
 +    }
 +}
 +
 +void LLPanelOutfitEdit::onReplaceMenuItemClicked(LLUUID selected_item_id)
 +{
 +    LLViewerInventoryItem* item = gInventory.getLinkedItem(selected_item_id);
 +
 +    if (item)
 +    {
 +        showFilteredWearablesListView(item->getWearableType());
 +    }
 +}
 +
 +void LLPanelOutfitEdit::onShopButtonClicked()
 +{
 +    static LLShopURLDispatcher url_resolver;
 +
 +    // will contain the resultant URL
 +    std::string url;
 +
 +    if (isAgentAvatarValid())
 +    {
 +        // try to get wearable type from 'Add More' panel first (EXT-7639)
 +        selection_info_t selection_info = getAddMorePanelSelectionType();
 +
 +        LLWearableType::EType type = selection_info.first;
 +
 +        if (selection_info.second > 1)
 +        {
 +            // the second argument is not important in this case: generic market place will be opened
 +            url = url_resolver.resolveURL(LLWearableType::WT_NONE, SEX_FEMALE);
 +        }
 +        else
 +        {
 +        if (type == LLWearableType::WT_NONE)
 +        {
 +            type = getCOFWearablesSelectionType();
 +        }
 +
 +        ESex sex = gAgentAvatarp->getSex();
 +
 +        // WT_INVALID comes for attachments
 +        if (type != LLWearableType::WT_INVALID && type != LLWearableType::WT_NONE)
 +        {
 +            url = url_resolver.resolveURL(type, sex);
 +        }
 +
 +        if (url.empty())
 +        {
 +                url = url_resolver.resolveURL(
 +                        mCOFWearables->getExpandedAccordionAssetType(), sex);
 +            }
 +        }
 +    }
 +    else
 +    {
 +        LL_WARNS() << "Agent avatar is invalid" << LL_ENDL;
 +
 +        // the second argument is not important in this case: generic market place will be opened
 +        url = url_resolver.resolveURL(LLWearableType::WT_NONE, SEX_FEMALE);
 +    }
 +
 +    LLWeb::loadURL(url);
 +}
 +
 +LLWearableType::EType LLPanelOutfitEdit::getCOFWearablesSelectionType() const
 +{
 +    std::vector<LLPanel*> selected_items;
 +    LLWearableType::EType type = LLWearableType::WT_NONE;
 +
 +    mCOFWearables->getSelectedItems(selected_items);
 +
 +    if (selected_items.size() == 1)
 +    {
 +        LLPanel* item = selected_items.front();
 +
 +        // LLPanelDummyClothingListItem is lower then LLPanelInventoryListItemBase in hierarchy tree
 +        if (LLPanelDummyClothingListItem* dummy_item = dynamic_cast<LLPanelDummyClothingListItem*>(item))
 +        {
 +            type = dummy_item->getWearableType();
 +        }
 +        else if (LLPanelInventoryListItemBase* real_item = dynamic_cast<LLPanelInventoryListItemBase*>(item))
 +        {
 +            type = real_item->getWearableType();
 +        }
 +    }
 +
 +    return type;
 +}
 +
 +LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionType() const
 +{
 +    selection_info_t result = std::make_pair(LLWearableType::WT_NONE, 0);
 +
 +    if (mAddWearablesPanel != NULL && mAddWearablesPanel->getVisible())
 +    {
 +        if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible())
 +        {
 +            std::set<LLFolderViewItem*> selected_items =    mInventoryItemsPanel->getRootFolder()->getSelectionList();
 +
 +            result.second = selected_items.size();
 +
 +            if (result.second == 1)
 +            {
 +                result.first = getWearableTypeByItemUUID(static_cast<LLFolderViewModelItemInventory*>((*selected_items.begin())->getViewModelItem())->getUUID());
 +            }
 +        }
 +        else if (mWearableItemsList != NULL && mWearableItemsList->getVisible())
 +        {
 +            std::vector<LLUUID> selected_uuids;
 +            mWearableItemsList->getSelectedUUIDs(selected_uuids);
 +
 +            result.second = selected_uuids.size();
 +
 +            if (result.second == 1)
 +            {
 +                result.first = getWearableTypeByItemUUID(selected_uuids.front());
 +            }
 +        }
 +    }
 +
 +    return result;
 +}
 +
 +LLWearableType::EType LLPanelOutfitEdit::getWearableTypeByItemUUID(const LLUUID& item_uuid) const
 +{
 +    LLViewerInventoryItem* item = gInventory.getLinkedItem(item_uuid);
 +    return (item != NULL) ? item->getWearableType() : LLWearableType::WT_NONE;
 +}
 +
 +void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void)
 +{
 +    LLUUID id_to_remove = mCOFWearables->getSelectedUUID();
 +    LLWearableType::EType type = getWearableTypeByItemUUID(id_to_remove);
 +
 +    LLAppearanceMgr::getInstance()->removeItemFromAvatar(id_to_remove);
 +
 +    if (!mCOFWearables->getSelectedItem())
 +    {
 +        mCOFWearables->selectClothing(type);
 +    }
 +}
 +
 +
 +void LLPanelOutfitEdit::onEditWearableClicked(void)
 +{
 +    LLUUID selected_item_id = mCOFWearables->getSelectedUUID();
 +    if (selected_item_id.notNull())
 +    {
 +        gAgentWearables.editWearable(selected_item_id);
 +    }
 +}
 +
 +void LLPanelOutfitEdit::updatePlusButton()
 +{
 +    uuid_vec_t selected_items;
 +    getSelectedItemsUUID(selected_items);
 +    if (selected_items.empty())
 +    {
 +        mPlusBtn->setEnabled(false);
 +        return;
 +    }
 +
 +    // If any of the selected items are not wearable (due to already being worn OR being of the wrong type), disable the add button.
 +    uuid_vec_t::iterator unwearable_item = std::find_if(selected_items.begin(), selected_items.end(), !boost::bind(&get_can_item_be_worn, _1));
 +    bool can_add = ( unwearable_item == selected_items.end() );
 +
 +    mPlusBtn->setEnabled(can_add);
 +
 +    LLViewerInventoryItem* first_item(gInventory.getItem(selected_items.front()));
 +
 +    if (can_add &&
 +        first_item &&
 +        selected_items.size() == 1 &&
 +        first_item->getType() == LLAssetType::AT_BODYPART)
 +    {
 +        mPlusBtn->setToolTip(getString("replace_body_part"));
 +    }
 +    else
 +    {
 +        mPlusBtn->setToolTip(LLStringUtil::null);
 +    }
 +
 +    /* 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::applyFolderViewFilter(EFolderViewItemType type)
 +{
 +    mFolderViewFilterCmbBox->setCurrentByIndex(type);
 +    mFolderViewFilterCmbBox->onCommit();
 +}
 +
 +void LLPanelOutfitEdit::applyListViewFilter(EListViewItemType type)
 +{
 +    mListViewFilterCmbBox->setCurrentByIndex(type);
 +    mListViewFilterCmbBox->onCommit();
 +}
 +
 +void LLPanelOutfitEdit::filterWearablesBySelectedItem(void)
 +{
 +    if (!mAddWearablesPanel->getVisible()) return;
 +
 +    uuid_vec_t ids;
 +    mCOFWearables->getSelectedUUIDs(ids);
 +
 +    bool nothing_selected = ids.empty();
 +    bool one_selected = ids.size() == 1;
 +    bool more_than_one_selected = ids.size() > 1;
 +    bool is_dummy_item = (ids.size() && dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem()));
 +
 +    // selected, expanded accordion tabs and selection in flat list view determine filtering when no item is selected in COF
 +    // selection in flat list view participates in determining filtering because of EXT-7963
 +    // So the priority of criterions in is:
 +    //                   1. Selected accordion tab            |  IF (any accordion selected)
 +    //                                                        |     filter_type = selected_accordion_type
 +    //                   2. Selected item in flat list view   |  ELSEIF (any item in flat list view selected)
 +    //                                                        |     filter_type = selected_item_type
 +    //                   3. Expanded accordion tab            |  ELSEIF (any accordion expanded)
 +    //                                                        |      filter_type = expanded accordion_type
 +    if (nothing_selected)
 +    {
 +        if (mInventoryItemsPanel->getVisible())
 +        {
 +            return;
 +        }
 +        showWearablesListView();
 +
 +        //selected accordion tab is more priority than expanded tab
 +        //and selected item in flat list view of 'Add more' panel when
 +        //determining filtering
 +        LLAssetType::EType type = mCOFWearables->getSelectedAccordionAssetType();
 +        if (type == LLAssetType::AT_NONE)
 +        { //no accordion selected
 +
 +            // when no accordion selected then selected item from flat list view
 +            // has more priority than expanded when determining filtering
 +            LLUUID selected_item_id = mWearableItemsList->getSelectedUUID();
 +            LLViewerInventoryItem* item = gInventory.getLinkedItem(selected_item_id);
 +            if(item)
 +        {
 +                showFilteredWearablesListView(item->getWearableType());
 +                return;
 +            }
 +
 +            // when no accordion selected and no selected items in flat list view
 +            // determine filtering according to expanded accordion
 +            type = mCOFWearables->getExpandedAccordionAssetType();
 +        }
 +
 +        switch (type)
 +        {
 +        case LLAssetType::AT_OBJECT:
 +            applyListViewFilter(LVIT_ATTACHMENT);
 +            break;
 +        case LLAssetType::AT_BODYPART:
 +            applyListViewFilter(LVIT_BODYPART);
 +            break;
 +        case LLAssetType::AT_CLOTHING:
 +        default:
 +            applyListViewFilter(LVIT_CLOTHING);
 +            break;
 +        }
 +
 +        return;
 +    }
 +
 +    //resetting selection if more than one item is selected
 +    if (more_than_one_selected)
 +    {
 +        if (mInventoryItemsPanel->getVisible())
 +        {
 +            applyFolderViewFilter(FVIT_ALL);
 +            return;
 +        }
 +
 +        showWearablesListView();
 +        applyListViewFilter(LVIT_ALL);
 +        return;
 +    }
 +
 +
 +    //filter wearables by a type represented by a dummy item
 +    if (one_selected && is_dummy_item)
 +    {
 +        if (mInventoryItemsPanel->getVisible())
 +        {
 +            applyFolderViewFilter(FVIT_WEARABLE);
 +            return;
 +        }
 +
 +        onAddWearableClicked();
 +        return;
 +    }
 +
 +    LLViewerInventoryItem* item = gInventory.getItem(ids[0]);
 +    if (!item && ids[0].notNull())
 +    {
 +        if (mInventoryItemsPanel->getVisible())
 +        {
 +            applyFolderViewFilter(FVIT_ALL);
 +            return;
 +        }
 +        //Inventory misses an item with non-zero id
 +        showWearablesListView();
 +        applyListViewFilter(LVIT_ALL);
 +        return;
 +    }
 +
 +    if (item && one_selected && !is_dummy_item)
 +    {
 +        if (item->isWearableType())
 +        {
 +            if (mInventoryItemsPanel->getVisible())
 +            {
 +                applyFolderViewFilter(FVIT_WEARABLE);
 +                return;
 +            }
 +            //single clothing or bodypart item is selected
 +            showFilteredWearablesListView(item->getWearableType());
 +            return;
 +        }
 +        else
 +        {
 +            if (mInventoryItemsPanel->getVisible())
 +            {
 +                applyFolderViewFilter(FVIT_ATTACHMENT);
 +                return;
 +            }
 +            //attachment is selected
 +            showWearablesListView();
 +            applyListViewFilter(LVIT_ATTACHMENT);
 +            return;
 +        }
 +    }
 +
 +}
 +
 +
 +
 +void LLPanelOutfitEdit::update()
 +{
 +    mCOFWearables->refresh();
 +
 +    updateVerbs();
 +}
 +
 +bool LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
 +                                          EDragAndDropType cargo_type,
 +                                          void* cargo_data,
 +                                          EAcceptance* accept,
 +                                          std::string& tooltip_msg)
 +{
 +    if (cargo_data == NULL)
 +    {
 +        LL_WARNS() << "cargo_data is NULL" << LL_ENDL;
 +        return true;
 +    }
 +
 +    switch (cargo_type)
 +    {
 +    case DAD_BODYPART:
 +    case DAD_CLOTHING:
 +    case DAD_OBJECT:
 +    case DAD_LINK:
 +        *accept = ACCEPT_YES_MULTI;
 +        break;
 +    default:
 +        *accept = ACCEPT_NO;
 +    }
 +
 +    if (drop)
 +    {
 +        LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data);
 +
 +        if (LLAssetType::lookupIsAssetIDKnowable(item->getType()))
 +        {
 +            mCOFDragAndDropObserver->watchAsset(item->getAssetUUID());
 +
 +            /*
 +             * Adding request to wear item. If the item is a link, then getLinkedUUID() will
 +             * return the ID of the linked item. Otherwise it will return the item's ID. The
 +             * second argument is used to delay the appearance update until all dragged items
 +             * are added to optimize user experience.
 +             */
 +            LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID());
 +        }
 +        else
 +        {
 +            // if asset id is not available for the item we must wear it immediately (attachments only)
 +            LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), new LLUpdateAppearanceAndEditWearableOnDestroy(item->getUUID()));
 +        }
 +    }
 +
 +    return true;
 +}
 +
 +void LLPanelOutfitEdit::displayCurrentOutfit()
 +{
 +    if (!getVisible())
 +    {
 +        setVisible(true);
 +    }
 +
 +    updateCurrentOutfitName();
 +
 +    update();
 +}
 +
 +void LLPanelOutfitEdit::updateCurrentOutfitName()
 +{
 +    std::string current_outfit_name;
 +    if (LLAppearanceMgr::getInstance()->getBaseOutfitName(current_outfit_name))
 +    {
 +        mCurrentOutfitName->setText(current_outfit_name);
 +    }
 +    else
 +    {
 +        mCurrentOutfitName->setText(getString("No Outfit"));
 +    }
 +}
 +
 +//private
 +void LLPanelOutfitEdit::updateVerbs()
 +{
 +    bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty();
 +    bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked();
 +    bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull();
 +
 +    getChildView(SAVE_BTN)->setEnabled(!outfit_locked && outfit_is_dirty);
 +    getChildView(REVERT_BTN)->setEnabled(outfit_is_dirty && has_baseoutfit);
 +
 +    mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing"));
 +
 +    updateCurrentOutfitName();
 +
 +    //updating state of "Wear Item" button previously known as "Plus" button
 +    updatePlusButton();
 +}
 +
 +bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel)
 +{
 +    if(switch_from_panel && switch_to_panel && !switch_to_panel->getVisible())
 +    {
 +        switch_from_panel->setVisible(false);
 +        switch_to_panel->setVisible(true);
 +        return true;
 +    }
 +    return false;
 +}
 +
 +void LLPanelOutfitEdit::resetAccordionState()
 +{
 +    if (mCOFWearables != NULL)
 +    {
 +        mCOFWearables->expandDefaultAccordionTab();
 +    }
 +    else
 +    {
 +        LL_WARNS() << "mCOFWearables is NULL" << LL_ENDL;
 +    }
 +}
 +
 +void LLPanelOutfitEdit::onAddMoreButtonClicked()
 +{
 +    toggleAddWearablesPanel();
 +    filterWearablesBySelectedItem();
 +}
 +
 +void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type)
 +{
 +    showAddWearablesPanel(true);
 +    showWearablesListView();
 +
 +    //e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE
 +    applyListViewFilter(static_cast<EListViewItemType>(LVIT_SHAPE + type));
 +    mWearableItemsList->setMenuWearableType(type);
 +}
 +
 +static void update_status_widget_rect(LLView * widget, S32 right_border)
 +{
 +    LLRect rect = widget->getRect();
 +    rect.mRight = right_border;
 +
 +    widget->setShape(rect);
 +}
 +
 +void LLPanelOutfitEdit::onOutfitChanging(bool started)
 +{
 +    static LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("edit_outfit_loading_indicator");
 +    static LLView* status_panel = getChild<LLView>("outfit_name_and_status");
 +    static S32 indicator_delta = status_panel->getRect().getWidth() - indicator->getRect().mLeft;
 +
 +    S32 delta = started ? indicator_delta : 0;
 +    S32 right_border = status_panel->getRect().getWidth() - delta;
 +
 +    if (mCurrentOutfitName)
 +        update_status_widget_rect(mCurrentOutfitName, right_border);
 +    if (mStatus)
 +        update_status_widget_rect(mStatus, right_border);
 +
 +    indicator->setVisible(started);
 +}
 +
 +void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id)
 +{
 +    if (mInventoryItemsPanel->getVisible())
 +    {
 +        LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem();
 +        if (!curr_item) return;
 +
 +        LLFolderViewModelItemInventory* listenerp  = static_cast<LLFolderViewModelItemInventory*>(curr_item->getViewModelItem());
 +        if (!listenerp) return;
 +
 +        selected_id = listenerp->getUUID();
 +    }
 +    else if (mWearablesListViewPanel->getVisible())
 +    {
 +        selected_id = mWearableItemsList->getSelectedUUID();
 +    }
 +}
 +
 +
 +void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list)
 +{
 +    void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back;
 +    if (mInventoryItemsPanel->getVisible())
 +    {
 +        std::set<LLFolderViewItem*> item_set =    mInventoryItemsPanel->getRootFolder()->getSelectionList();
 +        for (std::set<LLFolderViewItem*>::iterator it = item_set.begin(),    end_it = item_set.end();
 +            it != end_it;
 +            ++it)
 +        {
 +            uuid_list.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());
 +        }
 +    }
 +    else if (mWearablesListViewPanel->getVisible())
 +    {
 +        std::vector<LLSD> item_set;
 +        mWearableItemsList->getSelectedValues(item_set);
 +
 +        std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, boost::bind(&LLSD::asUUID, _1 )));
 +    }
 +
 +//  return selected_id;
 +}
 +
 +void LLPanelOutfitEdit::onCOFChanged()
 +{
 +    //the panel is only updated when is visible to a user
 +
 +    // BAP - this check has to be removed because otherwise item name
 +    // changes made when the panel is not visible will not be
 +    // propagated to the panel.
 +    // if (!isInVisibleChain()) return;
 +
 +    update();
 +}
 +
 +void LLPanelOutfitEdit::updateWearablesPanelVerbButtons()
 +{
 +    if(mWearablesListViewPanel->getVisible())
 +    {
 +        mFolderViewBtn->setToggleState(false);
 +        mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign());
 +        mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign());
 +    }
 +    else if(mInventoryItemsPanel->getVisible())
 +    {
 +        mListViewBtn->setToggleState(false);
 +        mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign());
 +        mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign());
 +    }
 +}
 +
 +void LLPanelOutfitEdit::saveListSelection()
 +{
 +    if(mWearablesListViewPanel->getVisible())
 +    {
 +        std::set<LLFolderViewItem*> selected_ids =    mInventoryItemsPanel->getRootFolder()->getSelectionList();
 +
 +        if(!selected_ids.size()) return;
 +
 +        for (std::set<LLFolderViewItem*>::const_iterator item_id =    selected_ids.begin(); item_id != selected_ids.end(); ++item_id)
 +        {
 +            mWearableItemsList->selectItemByUUID(static_cast<LLFolderViewModelItemInventory*>((*item_id)->getViewModelItem())->getUUID(),    true);
 +        }
 +        mWearableItemsList->scrollToShowFirstSelectedItem();
 +    }
 +    else if(mInventoryItemsPanel->getVisible())
 +    {
 +        std::vector<LLUUID> selected_ids;
 +        mWearableItemsList->getSelectedUUIDs(selected_ids);
 +
 +        if(!selected_ids.size()) return;
 +
 +        mInventoryItemsPanel->clearSelection();
 +        LLFolderView* root = mInventoryItemsPanel->getRootFolder();
 +
 +        if(!root) return;
 +
 +        for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id)
 +        {
 +            LLFolderViewItem* item = mInventoryItemsPanel->getItemByID(*item_id);
 +            if (!item) continue;
 +
 +            LLFolderViewFolder* parent = item->getParentFolder();
 +            if(parent)
 +            {
 +                parent->setOpenArrangeRecursively(true, LLFolderViewFolder::RECURSE_UP);
 +            }
 +            mInventoryItemsPanel->getRootFolder()->changeSelection(item, true);
 +        }
 +        mInventoryItemsPanel->getRootFolder()->scrollToShowSelection();
 +    }
 +}
 +
 +void LLPanelOutfitEdit::saveOutfit(bool as_new)
 +{
 +    LLPanelOutfitsInventory* panel_outfits_inventory = LLPanelOutfitsInventory::findInstance();
 +    if (panel_outfits_inventory)
 +    {
 +        panel_outfits_inventory->saveOutfit(as_new);
 +    }
 +}
 +
 +// EOF
  | 
