From a96f47db68dd52fa94bc3e9f652623583f85c60a Mon Sep 17 00:00:00 2001
From: Andrew Polunin <apolunin@productengine.com>
Date: Wed, 21 Jul 2010 19:00:57 +0300
Subject: [PATCH] EXT-8164 FIXED (Accordions should be reset to default state
 after Edit Outfit panel reopening)

Now accordion on panels 'Edit Outfit', 'Editing Shape', 'Editing Hair', 'Editing Eyes', 'Editing Skin', 'Group Profile' and 'Place Profile' are reset when the panels are closed and then opened again.

Reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/782/

--HG--
branch : product-engine
---
 indra/llui/llaccordionctrl.cpp          | 25 ++++++++++++++++
 indra/llui/llaccordionctrl.h            |  1 +
 indra/newview/llcofwearables.cpp        | 34 +++++++++++++++++-----
 indra/newview/llcofwearables.h          |  4 +++
 indra/newview/llpaneleditwearable.cpp   | 38 +++++++++++++++++++++++++
 indra/newview/llpaneleditwearable.h     |  5 ++++
 indra/newview/llpanelgroup.cpp          | 12 ++++++++
 indra/newview/llpanelgroup.h            |  3 +-
 indra/newview/llpaneloutfitedit.cpp     | 12 ++++++++
 indra/newview/llpaneloutfitedit.h       |  2 ++
 indra/newview/llpanelplaceprofile.cpp   |  9 +++++-
 indra/newview/llpanelplaceprofile.h     |  2 ++
 indra/newview/llsidepanelappearance.cpp | 21 ++++++++++++--
 13 files changed, 157 insertions(+), 11 deletions(-)

diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index 673631f99ad..2bc8ea054a8 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -811,6 +811,31 @@ void	LLAccordionCtrl::reset		()
 		mScrollbar->setDocPos(0);
 }
 
+void LLAccordionCtrl::expandDefaultTab()
+{
+	if (mAccordionTabs.size() > 0)
+	{
+		LLAccordionCtrlTab* tab = mAccordionTabs.front();
+
+		if (!tab->getDisplayChildren())
+		{
+			tab->setDisplayChildren(true);
+		}
+
+		for (size_t i = 1; i < mAccordionTabs.size(); ++i)
+		{
+			tab = mAccordionTabs[i];
+
+			if (tab->getDisplayChildren())
+			{
+				tab->setDisplayChildren(false);
+			}
+		}
+
+		arrange();
+	}
+}
+
 void LLAccordionCtrl::sort()
 {
 	if (!mTabComparator)
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
index b5fdf796cd7..8241ee15183 100644
--- a/indra/llui/llaccordionctrl.h
+++ b/indra/llui/llaccordionctrl.h
@@ -122,6 +122,7 @@ class LLAccordionCtrl: public LLPanel
 	S32		notifyParent(const LLSD& info);
 
 	void	reset		();
+	void	expandDefaultTab();
 
 	void	setComparator(const LLTabComparator* comp) { mTabComparator = comp; }
 	void	sort();
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index f75ea233516..f356a04fa4b 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -284,7 +284,8 @@ LLCOFWearables::LLCOFWearables() : LLPanel(),
 	mAttachmentsTab(NULL),
 	mBodyPartsTab(NULL),
 	mLastSelectedTab(NULL),
-	mCOFVersion(-1)
+	mCOFVersion(-1),
+	mAccordionCtrl(NULL)
 {
 	mClothingMenu = new CofClothingContextMenu(this);
 	mAttachmentMenu = new CofAttachmentContextMenu(this);
@@ -336,6 +337,8 @@ BOOL LLCOFWearables::postBuild()
 	mTab2AssetType[mAttachmentsTab] = LLAssetType::AT_OBJECT;
 	mTab2AssetType[mBodyPartsTab] = LLAssetType::AT_BODYPART;
 
+	mAccordionCtrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
+
 	return LLPanel::postBuild();
 }
 
@@ -652,18 +655,35 @@ LLAssetType::EType LLCOFWearables::getExpandedAccordionAssetType()
 	typedef std::map<std::string, LLAssetType::EType> type_map_t;
 
 	static type_map_t type_map;
-	static LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
-	const LLAccordionCtrlTab* expanded_tab = accordion_ctrl->getExpandedTab();
 
-	return get_if_there(mTab2AssetType, expanded_tab, LLAssetType::AT_NONE);
+	if (mAccordionCtrl != NULL)
+	{
+		const LLAccordionCtrlTab* expanded_tab = mAccordionCtrl->getExpandedTab();
+
+		return get_if_there(mTab2AssetType, expanded_tab, LLAssetType::AT_NONE);
 	}
 
+	return LLAssetType::AT_NONE;
+}
+
 LLAssetType::EType LLCOFWearables::getSelectedAccordionAssetType()
+{
+	if (mAccordionCtrl != NULL)
 	{
-	static LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
-	const LLAccordionCtrlTab* selected_tab = accordion_ctrl->getSelectedTab();
+		const LLAccordionCtrlTab* selected_tab = mAccordionCtrl->getSelectedTab();
 
-	return get_if_there(mTab2AssetType, selected_tab, LLAssetType::AT_NONE);
+		return get_if_there(mTab2AssetType, selected_tab, LLAssetType::AT_NONE);
+	}
+
+	return LLAssetType::AT_NONE;
+}
+
+void LLCOFWearables::expandDefaultAccordionTab()
+{
+	if (mAccordionCtrl != NULL)
+	{
+		mAccordionCtrl->expandDefaultTab();
+	}
 }
 
 void LLCOFWearables::onListRightClick(LLUICtrl* ctrl, S32 x, S32 y, LLListContextMenu* menu)
diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h
index d005b75eaae..cd7cc060e5f 100644
--- a/indra/newview/llcofwearables.h
+++ b/indra/newview/llcofwearables.h
@@ -40,6 +40,7 @@
 #include "llappearancemgr.h"
 #include "llinventorymodel.h"
 
+class LLAccordionCtrl;
 class LLAccordionCtrlTab;
 class LLListContextMenu;
 class LLPanelClothingListItem;
@@ -87,6 +88,7 @@ class LLCOFWearables : public LLPanel
 
 	LLAssetType::EType getExpandedAccordionAssetType();
 	LLAssetType::EType getSelectedAccordionAssetType();
+	void expandDefaultAccordionTab();
 
 	LLCOFCallbacks& getCOFCallbacks() { return mCOFCallbacks; }
 
@@ -125,6 +127,8 @@ class LLCOFWearables : public LLPanel
 	LLListContextMenu* mAttachmentMenu;
 	LLListContextMenu* mBodyPartMenu;
 
+	LLAccordionCtrl*	mAccordionCtrl;
+
 	/* COF category version since last refresh */
 	S32 mCOFVersion;
 };
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index ec685405eda..62e6cdc79d6 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -47,6 +47,7 @@
 #include "llvoavatarself.h"
 #include "lltexteditor.h"
 #include "lltextbox.h"
+#include "llaccordionctrl.h"
 #include "llaccordionctrltab.h"
 #include "llagentwearables.h"
 #include "llscrollingpanelparam.h"
@@ -666,6 +667,35 @@ void LLPanelEditWearable::updateAvatarHeightLabel()
 	mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param);
 }
 
+void LLPanelEditWearable::onWearablePanelVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl)
+{
+	if (in_visible_chain.asBoolean() && accordion_ctrl != NULL)
+	{
+		accordion_ctrl->expandDefaultTab();
+	}
+}
+
+void LLPanelEditWearable::setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel)
+{
+	if (bodypart_panel != NULL)
+	{
+		LLAccordionCtrl* accordion_ctrl = bodypart_panel->getChild<LLAccordionCtrl>("wearable_accordion");
+
+		if (accordion_ctrl != NULL)
+		{
+			bodypart_panel->setVisibleCallback(
+					boost::bind(&LLPanelEditWearable::onWearablePanelVisibilityChange, this, _2, accordion_ctrl));
+		}
+		else
+		{
+			llwarns << "accordion_ctrl is NULL" << llendl;
+		}
+	}
+	else
+	{
+		llwarns << "bodypart_panel is NULL" << llendl;
+	}
+}
 
 // virtual 
 BOOL LLPanelEditWearable::postBuild()
@@ -695,6 +725,14 @@ BOOL LLPanelEditWearable::postBuild()
 	mPanelEyes = getChild<LLPanel>("edit_eyes_panel");
 	mPanelHair = getChild<LLPanel>("edit_hair_panel");
 
+	// Setting the visibility callback is applied only to the bodyparts panel
+	// because currently they are the only ones whose 'wearable_accordion' has
+	// multiple accordion tabs (see EXT-8164 for details).
+	setWearablePanelVisibilityChangeCallback(mPanelShape);
+	setWearablePanelVisibilityChangeCallback(mPanelSkin);
+	setWearablePanelVisibilityChangeCallback(mPanelEyes);
+	setWearablePanelVisibilityChangeCallback(mPanelHair);
+
 	//clothes
 	mPanelShirt = getChild<LLPanel>("edit_shirt_panel");
 	mPanelPants = getChild<LLPanel>("edit_pants_panel");
diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h
index dbda90fe9fa..c0823dd3fad 100644
--- a/indra/newview/llpaneleditwearable.h
+++ b/indra/newview/llpaneleditwearable.h
@@ -39,6 +39,7 @@
 #include "llvoavatardefines.h"
 #include "llwearabletype.h"
 
+class LLAccordionCtrl;
 class LLCheckBoxCtrl;
 class LLWearable;
 class LLTextBox;
@@ -113,6 +114,10 @@ class LLPanelEditWearable : public LLPanel
 	// updates avatar height label
 	void updateAvatarHeightLabel();
 
+	void onWearablePanelVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl);
+
+	void setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel);
+
 	// the pointer to the wearable we're editing. NULL means we're not editing a wearable.
 	LLWearable *mWearablePtr;
 	LLViewerInventoryItem* mWearableItem;
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index d997b83cbbb..38e776b1951 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -182,6 +182,11 @@ BOOL LLPanelGroup::postBuild()
 	LLPanelGroupTab* panel_notices = findChild<LLPanelGroupTab>("group_notices_tab_panel");
 	LLPanelGroupTab* panel_land = findChild<LLPanelGroupTab>("group_land_tab_panel");
 
+	if (LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("groups_accordion"))
+	{
+		setVisibleCallback(boost::bind(&LLPanelGroup::onVisibilityChange, this, _2, accordion_ctrl));
+	}
+
 	if(panel_general)	mTabs.push_back(panel_general);
 	if(panel_roles)		mTabs.push_back(panel_roles);
 	if(panel_notices)	mTabs.push_back(panel_notices);
@@ -305,6 +310,13 @@ void LLPanelGroup::onBtnCancel()
 	onBackBtnClick();
 }
 
+void LLPanelGroup::onVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl)
+{
+	if (in_visible_chain.asBoolean() && accordion_ctrl != NULL)
+	{
+		accordion_ctrl->expandDefaultTab();
+	}
+}
 
 void LLPanelGroup::changed(LLGroupChange gc)
 {
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index 13a03b07135..2b21e9895af 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -42,6 +42,7 @@ class LLOfferInfo;
 const S32 UPDATE_MEMBERS_PER_FRAME = 500;
 
 // Forward declares
+class LLAccordionCtrl;
 class LLPanelGroupTab;
 class LLTabContainer;
 class LLAgent;
@@ -102,6 +103,7 @@ class LLPanelGroup : public LLPanel,
 	void onBackBtnClick();
 	void onBtnJoin();
 	void onBtnCancel();
+	void onVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl);
 
 	static void onBtnApply(void*);
 	static void onBtnRefresh(void*);
@@ -126,7 +128,6 @@ class LLPanelGroup : public LLPanel,
 
 	LLButton*		mButtonJoin;
 	LLUICtrl*		mJoinText;
-
 };
 
 class LLPanelGroupTab : public LLPanel
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index e12344ce9d0..c09aff44dae 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -1027,6 +1027,18 @@ bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch
 	return false;
 }
 
+void LLPanelOutfitEdit::resetAccordionState()
+{
+	if (mCOFWearables != NULL)
+	{
+		mCOFWearables->expandDefaultAccordionTab();
+	}
+	else
+	{
+		llwarns << "mCOFWearables is NULL" << llendl;
+	}
+}
+
 void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)
 {
 	if(!mGearMenu)
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index ad128b10556..13ceda98a6c 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -183,6 +183,8 @@ class LLPanelOutfitEdit : public LLPanel
 	 */
 	bool switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel);
 
+	void resetAccordionState();
+
 	virtual BOOL	handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 									  EDragAndDropType cargo_type,
 									  void* cargo_data,
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index 1f979b0ef18..08835dc2b8c 100644
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -79,7 +79,8 @@ LLPanelPlaceProfile::LLPanelPlaceProfile()
 :	LLPanelPlaceInfo(),
 	mForSalePanel(NULL),
 	mYouAreHerePanel(NULL),
-	mSelectedParcelID(-1)
+	mSelectedParcelID(-1),
+	mAccordionCtrl(NULL)
 {}
 
 // virtual
@@ -139,6 +140,7 @@ BOOL LLPanelPlaceProfile::postBuild()
 	mSubdivideText = getChild<LLTextEditor>("subdivide");
 	mResaleText = getChild<LLTextEditor>("resale");
 	mSaleToText = getChild<LLTextBox>("sale_to");
+	mAccordionCtrl = getChild<LLAccordionCtrl>("advanced_info_accordion");
 
 	icon_pg = getString("icon_PG");
 	icon_m = getString("icon_M");
@@ -278,6 +280,11 @@ void LLPanelPlaceProfile::handleVisibilityChange(BOOL new_visibility)
 			parcel_mgr->deselectUnused();
 		}
 	}
+
+	if (mAccordionCtrl != NULL)
+	{
+		mAccordionCtrl->expandDefaultTab();
+	}
 }
 
 void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h
index e77b4415671..49c13ff5e37 100644
--- a/indra/newview/llpanelplaceprofile.h
+++ b/indra/newview/llpanelplaceprofile.h
@@ -35,6 +35,7 @@
 
 #include "llpanelplaceinfo.h"
 
+class LLAccordionCtrl;
 class LLIconCtrl;
 class LLTextEditor;
 
@@ -118,6 +119,7 @@ class LLPanelPlaceProfile : public LLPanelPlaceInfo
 	LLTextEditor*		mSubdivideText;
 	LLTextEditor*		mResaleText;
 	LLTextBox*			mSaleToText;
+	LLAccordionCtrl*	mAccordionCtrl;
 };
 
 #endif // LL_LLPANELPLACEPROFILE_H
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 7a7ffb99838..98cd0b88ebe 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -190,13 +190,16 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
 {
 	if (new_visibility.asBoolean())
 	{
-		if ((mOutfitEdit && mOutfitEdit->getVisible()) || (mEditWearable && mEditWearable->getVisible()))
+		bool is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
+		bool is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
+
+		if (is_outfit_edit_visible || is_wearable_edit_visible)
 		{
 			if (!gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement"))
 			{
 				gAgentCamera.changeCameraToCustomizeAvatar();
 			}
-			if (mEditWearable && mEditWearable->getVisible())
+			if (is_wearable_edit_visible)
 			{
 				LLWearable *wearable_ptr = mEditWearable->getWearable();
 				if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
@@ -205,6 +208,11 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
 					showOutfitEditPanel();
 				}
 			}
+
+			if (is_outfit_edit_visible)
+			{
+				mOutfitEdit->resetAccordionState();
+			}
 		}
 	}
 	else
@@ -283,6 +291,15 @@ void LLSidepanelAppearance::showOutfitsInventoryPanel()
 
 void LLSidepanelAppearance::showOutfitEditPanel()
 {
+	// Accordion's state must be reset in all cases except the one when user
+	// is returning back to the mOutfitEdit panel from the mEditWearable panel.
+	// The simplest way to control this is to check the visibility state of the mEditWearable
+	// BEFORE it is changed by the call to the toggleWearableEditPanel(FALSE, NULL, TRUE).
+	if (mEditWearable != NULL && !mEditWearable->getVisible() && mOutfitEdit != NULL)
+	{
+		mOutfitEdit->resetAccordionState();
+	}
+
 	togglMyOutfitsPanel(FALSE);
 	toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode
 	toggleOutfitEditPanel(TRUE);
-- 
GitLab