diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 82ec02d2ebc66df50590332039ae8ef11a294cb2..ce068618e20c5caf1fe891456b9d4d04472362ee 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -26,6 +26,8 @@ include_directories(
     )
 
 set(llui_SOURCE_FILES
+    llaccordionctrl.cpp
+    llaccordionctrltab.cpp
     llbutton.cpp
     llcheckboxctrl.cpp
     llclipboard.cpp
@@ -111,6 +113,8 @@ set(llui_SOURCE_FILES
 set(llui_HEADER_FILES
     CMakeLists.txt
 
+    llaccordionctrl.h
+    llaccordionctrltab.h
     llbutton.h
     llcallbackmap.h
     llcheckboxctrl.h
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b5e870228ad68f9ab140abf6b99773e725cc3d29
--- /dev/null
+++ b/indra/llui/llaccordionctrl.cpp
@@ -0,0 +1,578 @@
+/** 
+ * @file llaccordionctrl.cpp
+ * @brief Accordion panel  implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+
+#include "lluictrlfactory.h" // builds floaters from XML
+
+#include "llwindow.h"
+#include "llfocusmgr.h"
+#include "lllocalcliprect.h"
+
+#include "boost/bind.hpp"
+
+static const S32 DRAGGER_BAR_MARGIN = 4;
+static const S32 DRAGGER_BAR_HEIGHT = 5;
+static const S32 BORDER_MARGIN = 2;
+static const S32 PARENT_BORDER_MARGIN = 5;
+
+static const S32 panel_delta = DRAGGER_BAR_MARGIN;  // Distanse between two panels 
+
+static const S32 HORIZONTAL_MULTIPLE = 8;
+static const S32 VERTICAL_MULTIPLE = 16;
+static const F32 MIN_AUTO_SCROLL_RATE = 120.f;
+static const F32 MAX_AUTO_SCROLL_RATE = 500.f;
+static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
+
+
+// LLAccordionCtrl =================================================================|
+
+static LLDefaultChildRegistry::Register<LLAccordionCtrl>	t2("accordion");
+
+
+LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
+ , mFitParent(params.fit_parent)
+{
+  mSingleExpansion = params.single_expansion;
+	if(mFitParent && !mSingleExpansion)
+	{
+		llinfos << "fit_parent works best when combined with single_expansion" << llendl;
+	}
+}
+
+LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
+{
+	mSingleExpansion = false;
+	mFitParent = false;
+	LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml");	
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::draw()
+{
+	LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+	
+	LLLocalClipRect clip(local_rect);
+	
+	LLPanel::draw();
+}
+
+
+//---------------------------------------------------------------------------------
+BOOL LLAccordionCtrl::postBuild()
+{
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+	LLRect scroll_rect;
+	scroll_rect.setOriginAndSize( 
+		getRect().getWidth() - scrollbar_size,
+		1,
+		scrollbar_size,
+		getRect().getHeight() - 1);
+	
+
+	LLScrollbar::Params sbparams;
+	sbparams.name("scrollable vertical");
+	sbparams.rect(scroll_rect);
+	sbparams.orientation(LLScrollbar::VERTICAL);
+	sbparams.doc_size(mInnerRect.getHeight());
+	sbparams.doc_pos(0);
+	sbparams.page_size(mInnerRect.getHeight());
+	sbparams.step_size(VERTICAL_MULTIPLE);
+	sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+	sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2));
+	
+	mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
+	LLView::addChild( mScrollbar );
+	mScrollbar->setVisible( false );
+	mScrollbar->setFollowsRight();
+	mScrollbar->setFollowsTop();
+	mScrollbar->setFollowsBottom();
+
+	//if it was created from xml...
+	std::vector<LLUICtrl*> accordion_tabs;
+	for(child_list_const_iter_t it = getChildList()->begin(); 
+		getChildList()->end() != it; ++it)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*it);
+		if(accordion_tab == NULL)
+			continue;
+		if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end())
+		{
+			accordion_tabs.push_back(accordion_tab);
+		}
+	}
+
+	for(std::vector<LLUICtrl*>::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it)
+		addCollapsibleCtrl(*it);
+
+	arrange	();
+
+	if(mSingleExpansion)
+	{
+		if(!mAccordionTabs[0]->getDisplayChildren())
+			mAccordionTabs[0]->setDisplayChildren(true);
+		for(size_t i=1;i<mAccordionTabs.size();++i)
+		{
+			if(mAccordionTabs[i]->getDisplayChildren())
+				mAccordionTabs[i]->setDisplayChildren(false);
+		}
+	}
+
+	return TRUE;
+}
+
+
+//---------------------------------------------------------------------------------
+LLAccordionCtrl::~LLAccordionCtrl()
+{
+  mAccordionTabs.clear();
+}
+
+//---------------------------------------------------------------------------------
+
+void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+	// adjust our rectangle
+	LLRect rcLocal = getRect();
+	rcLocal.mRight = rcLocal.mLeft + width;
+	rcLocal.mTop = rcLocal.mBottom + height;
+
+	setRect(rcLocal);
+
+	arrange();
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+	return LLPanel::handleRightMouseDown(x, y, mask);
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta)
+{
+	for(size_t i = panel_num; i < mAccordionTabs.size(); i++ )
+	{
+		ctrlShiftVertical(mAccordionTabs[i],delta);
+	}	
+}
+
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) 
+{
+	if(mSingleExpansion)
+	{
+		for(size_t i=0;i<mAccordionTabs.size();++i)
+		{
+			if(i==panel_num)
+				continue;
+			if(mAccordionTabs[i]->getDisplayChildren())
+				mAccordionTabs[i]->setDisplayChildren(false);
+		}
+
+	}
+	arrange();
+}
+
+void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height)
+{
+	calcRecuiredHeight();
+	if(getRecuiredHeight() > height )
+		showScrollbar(width,height);
+	else
+		hideScrollbar(width,height);
+}
+
+void	LLAccordionCtrl::showScrollbar(S32 width, S32 height)
+{
+	bool was_visible = mScrollbar->getVisible();
+
+	mScrollbar->setVisible(true);
+	
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+	ctrlSetLeftTopAndSize(mScrollbar
+		,width-scrollbar_size - PARENT_BORDER_MARGIN/2
+		,height-PARENT_BORDER_MARGIN
+		,scrollbar_size
+		,height-2*PARENT_BORDER_MARGIN);
+	
+	mScrollbar->setPageSize(height);
+	mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos());
+
+	if(was_visible)
+	{
+		S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1);
+		mScrollbar->setDocPos(scroll_pos);
+	}
+}
+
+void	LLAccordionCtrl::hideScrollbar( S32 width, S32 height )
+{
+	if(mScrollbar->getVisible() == false)
+		return;
+	mScrollbar->setVisible(false);
+
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+	S32 panel_width = width - 2*BORDER_MARGIN;
+
+	//reshape all accordeons and shift all draggers
+	for(size_t i=0;i<mAccordionTabs.size();++i)
+	{
+		LLRect panel_rect = mAccordionTabs[i]->getRect();
+		ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight());
+	}
+
+	mScrollbar->setDocPos(0);
+
+	if(mAccordionTabs.size()>0)
+	{
+		S32 panel_top = height - BORDER_MARGIN;		  // Top coordinate of the first panel
+		S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop;
+		shiftAccordionTabs(0,diff);
+	}
+}
+
+
+//---------------------------------------------------------------------------------
+S32 LLAccordionCtrl::calcRecuiredHeight()
+{
+	S32 rec_height = 0;
+	
+	std::vector<LLAccordionCtrlTab*>::iterator panel;
+	for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*panel);
+		if(accordion_tab && accordion_tab->getVisible())
+		{
+			rec_height += accordion_tab->getRect().getHeight();
+		}
+	}
+
+	mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN);
+
+	return mInnerRect.getHeight();
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
+{
+	if(!panel)
+		return;
+	LLRect panel_rect = panel->getRect();
+	panel_rect.setLeftTopAndSize( left, top, width, height);
+	panel->reshape( width, height, 1);
+	panel->setRect(panel_rect);
+}
+
+void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta)
+{
+	if(!panel)
+		return;
+	panel->translate(0,delta);
+}
+
+//---------------------------------------------------------------------------------
+
+void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
+{
+	LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(view);
+	if(!accordion_tab)
+		return;
+	if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) == getChildList()->end())
+		addChild(accordion_tab);
+	mAccordionTabs.push_back(accordion_tab);
+	
+	accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) );
+
+}
+
+
+void LLAccordionCtrl::arrange()
+{
+	if( mAccordionTabs.size() == 0)
+	{
+		//We do not arrange if we do not have what should be arranged
+		return;
+	}
+
+	//Calculate params	
+	S32 panel_left = BORDER_MARGIN;	  // Margin from left side of Splitter
+	S32 panel_top = getRect().getHeight() - BORDER_MARGIN;		  // Top coordinate of the first panel
+	S32 panel_width = getRect().getWidth() - 4;		  // Top coordinate of the first panel
+
+	
+	if(mAccordionTabs.size() == 1)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
+		
+		LLRect panel_rect = accordion_tab->getRect();
+		
+		S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
+
+		ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
+		
+		show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
+		return;
+
+	}
+
+	for(size_t i = 0; i < mAccordionTabs.size(); i++ )
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+		
+		if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
+			continue;
+		
+		if(!accordion_tab->isExpanded() )
+		{
+			ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight());
+			panel_top-=mAccordionTabs[i]->getRect().getHeight();
+		}
+		else
+		{
+			S32 panel_height = accordion_tab->getRect().getHeight();
+			
+			if(mFitParent)
+			{
+				// all expanded tabs will have equal height
+				panel_height = calcExpandedTabHeight(i, panel_top);
+				ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height);
+
+				// try to make accordion tab fit accordion view height.
+				// Accordion View should implement getRequiredRect() and provide valid height
+				S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight();
+				optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN;
+				if(optimal_height < panel_height)
+				{
+					panel_height = optimal_height;
+				}
+
+				// minimum tab height is equal to header height
+				if(mAccordionTabs[i]->getHeaderHeight() > panel_height)
+				{
+					panel_height = mAccordionTabs[i]->getHeaderHeight();
+				}
+			}
+			
+			ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
+			panel_top-=panel_height;
+			
+		}
+	}	
+
+	show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
+
+	updateLayout(getRect().getWidth(),getRect().getHeight());
+
+}
+
+//---------------------------------------------------------------------------------
+
+BOOL LLAccordionCtrl::handleScrollWheel		( S32 x, S32 y, S32 clicks )
+{
+	if(LLPanel::handleScrollWheel(x,y,clicks))
+		return TRUE;
+	if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
+		return TRUE;
+	return false;
+
+}
+
+BOOL LLAccordionCtrl::handleKeyHere			(KEY key, MASK mask)
+{
+	if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) )
+		return TRUE;
+	return LLPanel::handleKeyHere(key,mask);
+}
+
+void	LLAccordionCtrl::updateLayout	(S32 width, S32 height)
+{
+	S32 panel_top = height - BORDER_MARGIN ;
+	if(mScrollbar->getVisible())
+		panel_top+=mScrollbar->getDocPos();
+
+	S32 panel_width = width - 2*BORDER_MARGIN;
+
+	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+	if(mScrollbar->getVisible())
+		panel_width-=scrollbar_size;
+
+	//set sizes for first panels and dragbars
+	for(size_t i=0;i<mAccordionTabs.size();++i)
+	{
+		if(!mAccordionTabs[i]->getVisible())
+			continue;
+		LLRect panel_rect = mAccordionTabs[i]->getRect();
+		ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
+		panel_top-=panel_rect.getHeight();
+	}
+}
+
+void	LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
+{
+	updateLayout(getRect().getWidth(),getRect().getHeight());
+}
+void	LLAccordionCtrl::onOpen		(const LLSD& key)
+{
+	for(size_t i=0;i<mAccordionTabs.size();++i)
+	{
+		LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+		LLPanel* panel = dynamic_cast<LLPanel*>(accordion_tab->getAccordionView());
+		if(panel!=NULL)
+		{
+			panel->onOpen(key);
+		}
+	}
+}
+S32	LLAccordionCtrl::notifyParent(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "size_changes")
+		{
+			//
+			arrange();
+			return 1;
+		}
+		else if(str_action == "select_next")
+		{
+			for(size_t i=0;i<mAccordionTabs.size();++i)
+			{
+				LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+				if(accordion_tab->hasFocus())
+				{
+					while(++i<mAccordionTabs.size())
+					{
+						if(mAccordionTabs[i]->getVisible())
+							break;
+					}
+					if(i<mAccordionTabs.size())
+					{
+						accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+						accordion_tab->notify(LLSD().with("action","select_first"));
+						return 1;
+					}
+					break;
+				}
+			}
+			return 0;
+		}
+		else if(str_action == "select_prev")
+		{
+			for(size_t i=0;i<mAccordionTabs.size();++i)
+			{
+				LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+				if(accordion_tab->hasFocus() && i>0)
+				{
+					while(i>0)
+					{
+						if(mAccordionTabs[--i]->getVisible())
+							break;
+					}
+					
+					accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+					accordion_tab->notify(LLSD().with("action","select_last"));
+					return 1;
+				}
+			}
+			return 0;
+		}
+	}
+	else if (info.has("scrollToShowRect"))
+	{
+		LLRect screen_rc, local_rc;
+		screen_rc.setValue(info["scrollToShowRect"]);
+		screenRectToLocal(screen_rc, &local_rc);
+
+		// Translate to parent coordinatess to check if we are in visible rectangle
+		local_rc.translate( getRect().mLeft, getRect().mBottom );
+
+		if ( !getRect().contains (local_rc) )
+		{
+			// Back to local coords and calculate position for scroller
+			S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom;
+			S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop;
+
+			S32 scroll_pos = llclamp(mScrollbar->getDocPos(),
+									 bottom, // min vertical scroll
+									 top); // max vertical scroll 
+
+			mScrollbar->setDocPos( scroll_pos );
+		}
+		return 1;
+	}
+	return LLPanel::notifyParent(info);
+}
+void	LLAccordionCtrl::reset		()
+{
+	if(mScrollbar)
+		mScrollbar->setDocPos(0);
+}
+
+S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)
+{
+	if(tab_index < 0)
+	{
+		return available_height;
+	}
+
+	S32 collapsed_tabs_height = 0;
+	S32 num_expanded = 0;
+
+	for(size_t n = tab_index; n < mAccordionTabs.size(); ++n)
+	{
+		if(!mAccordionTabs[n]->isExpanded())
+		{
+			collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight();
+		}
+		else
+		{
+			++num_expanded;
+		}
+	}
+
+	if(0 == num_expanded)
+	{
+		return available_height;
+	}
+
+	S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN
+	expanded_tab_height /= num_expanded;
+	return expanded_tab_height;
+}
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cb0f382813ab9ef14fba7f462ab451751c91606
--- /dev/null
+++ b/indra/llui/llaccordionctrl.h
@@ -0,0 +1,123 @@
+/** 
+ * @file LLAccordionCtrl.h
+ * @brief Accordion Panel implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * 
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCORDIONCTRL_H
+#define LL_ACCORDIONCTRL_H
+
+#include "llpanel.h"
+#include "llscrollbar.h"
+
+#include <vector>
+#include <algorithm>
+#include <string>
+
+class LLAccordionCtrlTab;
+
+class LLAccordionCtrl: public LLPanel
+{
+private:
+
+	std::vector<LLAccordionCtrlTab*> mAccordionTabs;
+
+	void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height);
+	void ctrlShiftVertical(LLView* panel,S32 delta);
+	
+	void onCollapseCtrlCloseOpen(S16 panel_num); 
+	void shiftAccordionTabs(S16 panel_num, S32 delta);
+
+
+public:
+	struct Params 
+		: public LLInitParam::Block<Params, LLPanel::Params>
+	{
+		Optional<bool>			single_expansion,
+								fit_parent; /* Accordion will fit its parent size, controls that are placed into 
+								accordion tabs are responsible for scrolling their content.
+								*NOTE fit_parent works best when combined with single_expansion.
+								Accordion view should implement getRequiredRect() and provide valid height*/
+
+		Params()
+			: single_expansion("single_expansion",false)
+			, fit_parent("fit_parent", false)
+		{};
+	};
+
+	LLAccordionCtrl(const Params& params);
+
+    LLAccordionCtrl();
+    virtual ~LLAccordionCtrl();
+
+	virtual BOOL postBuild();
+	
+	virtual BOOL handleRightMouseDown	( S32 x, S32 y, MASK mask); 
+	virtual BOOL handleScrollWheel		( S32 x, S32 y, S32 clicks );
+	virtual BOOL handleKeyHere			(KEY key, MASK mask);
+	//
+
+	// Call reshape after changing splitter's size
+	virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+	void addCollapsibleCtrl(LLView* view);
+	void arrange();
+
+
+	void	draw();
+	
+	void	onScrollPosChangeCallback(S32, LLScrollbar*);
+
+	void	onOpen		(const LLSD& key);
+	S32		notifyParent(const LLSD& info);
+
+	void	reset		();
+
+private:
+	// Calc Splitter's height that is necessary to display all child content
+	S32		calcRecuiredHeight();
+	S32		getRecuiredHeight() const { return mInnerRect.getHeight(); }
+	S32		calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0);
+
+	void	updateLayout			(S32 width, S32 height);
+
+	void	show_hide_scrollbar		(S32 width, S32 height);
+
+	void	showScrollbar			(S32 width, S32 height);
+	void	hideScrollbar			(S32 width, S32 height);
+
+private:
+	LLRect			mInnerRect;
+	LLScrollbar*	mScrollbar;
+	bool			mSingleExpansion;
+	bool			mFitParent;
+};
+
+
+#endif // LL_LLSPLITTER_H
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d6ba57c29a21a1f3ee8a7cbbaecbc28aacc01e6
--- /dev/null
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -0,0 +1,599 @@
+/** 
+ * @file LLAccordionCtrlTab.cpp
+ * @brief Collapsible control implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lluictrl.h"
+
+#include "llaccordionctrltab.h"
+
+#include "lltextbox.h"
+
+static const std::string DD_BUTTON_NAME = "dd_button";
+static const std::string DD_TEXTBOX_NAME = "dd_textbox";
+static const std::string DD_HEADER_NAME = "dd_header";
+
+static const S32 HEADER_HEIGHT = 20;
+static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;
+static const S32 HEADER_TEXT_LEFT_OFFSET = 30;
+
+static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab");
+
+class LLAccordionCtrlTab::LLAccordionCtrlTabHeader : public LLUICtrl
+{
+public:
+	friend class LLUICtrlFactory;
+
+	struct Params : public LLInitParam::Block<Params, LLAccordionCtrlTab::Params>
+	{
+		Params();
+	};
+
+	LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p);
+	
+	virtual ~LLAccordionCtrlTabHeader();
+
+	virtual void draw();
+
+	virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+	virtual BOOL postBuild();
+
+	void	setTitle(const std::string& title);
+
+	virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+	virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+private:
+
+	LLTextBox* mHeaderTextbox;
+
+	// Overlay images (arrows)
+	LLPointer<LLUIImage> mImageCollapsed;
+	LLPointer<LLUIImage> mImageExpanded;
+	LLPointer<LLUIImage> mImageCollapsedPressed;
+	LLPointer<LLUIImage> mImageExpandedPressed;
+
+	// Background images
+	LLPointer<LLUIImage> mImageHeader;
+	LLPointer<LLUIImage> mImageHeaderOver;
+	LLPointer<LLUIImage> mImageHeaderPressed;
+	LLPointer<LLUIImage> mImageHeaderFocused;
+
+	LLUIColor mHeaderBGColor;
+
+	bool mNeedsHighlight;
+};
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params()
+{
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader(
+	const LLAccordionCtrlTabHeader::Params& p)
+: LLUICtrl(p)
+, mHeaderBGColor(p.header_bg_color())
+,mNeedsHighlight(false),
+	mImageCollapsed(p.header_collapse_img),
+	mImageCollapsedPressed(p.header_collapse_img_pressed),
+	mImageExpanded(p.header_expand_img),
+	mImageExpandedPressed(p.header_expand_img_pressed),
+	mImageHeader(p.header_image),
+	mImageHeaderOver(p.header_image_over),
+	mImageHeaderPressed(p.header_image_pressed),
+	mImageHeaderFocused(p.header_image_focused)
+{
+	LLTextBox::Params textboxParams;
+	textboxParams.name(DD_TEXTBOX_NAME);
+	textboxParams.initial_value(p.title());
+	textboxParams.text_color(p.header_text_color());
+	textboxParams.follows.flags(FOLLOWS_NONE);
+	textboxParams.font( p.font() );
+	textboxParams.font_shadow(LLFontGL::NO_SHADOW);
+	textboxParams.use_ellipses = true;
+	textboxParams.bg_visible = false;
+	textboxParams.mouse_opaque = false;
+	mHeaderTextbox = LLUICtrlFactory::create<LLTextBox>(textboxParams);
+	addChild(mHeaderTextbox);
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader()
+{
+}
+
+BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild()
+{
+	return TRUE;
+}
+
+void	LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title)
+{
+	if(mHeaderTextbox)
+		mHeaderTextbox->setText(title);
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw()
+{
+	S32 width = getRect().getWidth();
+	S32 height = getRect().getHeight();
+
+	gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get(),true);
+
+	LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent());
+	bool collapsible = (parent && parent->getCollapsible());
+	bool expanded = (parent && parent->getDisplayChildren());
+
+	// Handle overlay images, if needed
+	// Only show green "focus" background image if the accordion is open,
+	// because the user's mental model of focus is that it goes away after
+	// the accordion is closed.
+	if (getParent()->hasFocus()
+		&& !(collapsible && !expanded))
+	{
+		mImageHeaderFocused->draw(0,0,width,height);
+	}
+	else
+	{
+		mImageHeader->draw(0,0,width,height);
+	}
+
+	if(mNeedsHighlight)
+	{
+		mImageHeaderOver->draw(0,0,width,height);
+	}
+	
+
+	if(collapsible)
+	{
+		LLPointer<LLUIImage> overlay_image;
+		if(expanded)
+		{
+			overlay_image = mImageExpanded;
+		}
+		else
+		{
+			overlay_image = mImageCollapsed;
+		}
+		overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET,
+							(height - overlay_image->getHeight()) / 2);
+	}
+	
+	LLUICtrl::draw();
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+	S32 header_height = mHeaderTextbox->getTextPixelHeight();
+
+	LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2);
+	mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight());
+	mHeaderTextbox->setRect(textboxRect);
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+	LLUICtrl::onMouseEnter(x, y, mask);
+	mNeedsHighlight = true;
+}
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+	LLUICtrl::onMouseLeave(x, y, mask);
+	mNeedsHighlight = false;
+}
+BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+	if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE)
+	{
+		return getParent()->handleKey(key, mask, called_from_parent);
+	}
+	return LLUICtrl::handleKey(key, mask, called_from_parent);
+}
+
+
+LLAccordionCtrlTab::Params::Params()
+	: title("title")
+	,display_children("expanded", true)
+	,header_height("header_height", HEADER_HEIGHT),
+	min_width("min_width", 0),
+	min_height("min_height", 0)
+	,collapsible("collapsible", true)
+	,header_bg_color("header_bg_color")
+	,dropdown_bg_color("dropdown_bg_color")
+	,header_visible("header_visible",true)
+	,padding_left("padding_left",2)
+	,padding_right("padding_right",2)
+	,padding_top("padding_top",2)
+	,padding_bottom("padding_bottom",2)
+	,header_expand_img("header_expand_img")
+	,header_expand_img_pressed("header_expand_img_pressed")
+	,header_collapse_img("header_collapse_img")
+	,header_collapse_img_pressed("header_collapse_img_pressed")
+	,header_image("header_image")
+	,header_image_over("header_image_over")
+	,header_image_pressed("header_image_pressed")
+	,header_image_focused("header_image_focused")
+	,header_text_color("header_text_color")
+{
+	mouse_opaque(false);
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
+	: LLUICtrl(p)
+	,mDisplayChildren(p.display_children)
+	,mCollapsible(p.collapsible)
+	,mExpandedHeight(0)
+	,mDropdownBGColor(p.dropdown_bg_color())
+	,mHeaderVisible(p.header_visible)
+	,mPaddingLeft(p.padding_left)
+	,mPaddingRight(p.padding_right)
+	,mPaddingTop(p.padding_top)
+	,mPaddingBottom(p.padding_bottom)
+	,mCanOpenClose(true)
+{
+	mStoredOpenCloseState = false;
+	mWasStateStored = false;
+	
+	mDropdownBGColor = LLColor4::white;
+	LLAccordionCtrlTabHeader::Params headerParams;
+	headerParams.name(DD_HEADER_NAME);
+	headerParams.title(p.title);
+	mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams);
+	addChild(mHeader, 1);
+
+	reshape(100, 200,FALSE);
+}
+
+LLAccordionCtrlTab::~LLAccordionCtrlTab()
+{
+}
+
+
+void LLAccordionCtrlTab::setDisplayChildren(bool display)
+{
+	mDisplayChildren = display;
+	LLRect rect = getRect();
+
+	rect.mBottom = rect.mTop - (getDisplayChildren() ? 
+		mExpandedHeight : HEADER_HEIGHT);
+	setRect(rect);
+
+	for(child_list_const_iter_t it = getChildList()->begin();
+		getChildList()->end() != it; ++it)
+	{
+		LLView* child = *it;
+		if(DD_HEADER_NAME == child->getName())
+			continue;
+
+		child->setVisible(getDisplayChildren());
+	}
+}
+
+void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+	LLRect headerRect;
+
+	LLUICtrl::reshape(width, height, TRUE);
+
+	headerRect.setLeftTopAndSize(
+		0,height,width,HEADER_HEIGHT);
+	mHeader->setRect(headerRect);
+	mHeader->reshape(headerRect.getWidth(), headerRect.getHeight());
+
+	for(child_list_const_iter_t it = getChildList()->begin(); 
+		getChildList()->end() != it; ++it)
+	{
+		LLView* child = *it;
+		if(DD_HEADER_NAME == child->getName())
+			continue;
+		if(!child->getVisible())
+			continue;
+
+		LLRect childRect = child->getRect();
+		S32 childWidth = width - getPaddingLeft() - getPaddingRight();
+		S32 childHeight = height - getHeaderHeight() - getPaddingTop() - getPaddingBottom();
+
+		child->reshape(childWidth,childHeight);
+		
+		childRect.setLeftTopAndSize(
+			getPaddingLeft(),
+			childHeight + getPaddingBottom(),
+			childWidth, 
+			childHeight);
+
+		child->setRect(childRect);
+		
+		break;//suppose that there is only one panel
+	}
+
+}
+
+void LLAccordionCtrlTab::changeOpenClose(bool is_open)
+{
+	if(is_open)
+		mExpandedHeight = getRect().getHeight();
+
+	setDisplayChildren(!is_open);
+	reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+	if (mCommitSignal)
+	{
+		(*mCommitSignal)(this, getDisplayChildren());
+	}
+}
+
+BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+	if(mCollapsible && mHeaderVisible && mCanOpenClose)
+	{
+		if(y >= (getRect().getHeight() - HEADER_HEIGHT) )
+		{
+			LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+			header->setFocus(true);
+			changeOpenClose(getDisplayChildren());
+
+			//reset stored state
+			mWasStateStored = false;
+			return TRUE;
+		}
+	}
+	return LLUICtrl::handleMouseDown(x,y,mask);
+}
+
+BOOL LLAccordionCtrlTab::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+	return LLUICtrl::handleMouseUp(x,y,mask);
+}
+
+boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(commit_callback_t cb)
+{
+	return setCommitCallback(cb);
+}
+
+bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group)
+{
+	if(DD_HEADER_NAME != child->getName())
+	{
+		reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT );
+		mExpandedHeight = getRect().getHeight();
+	}
+
+	bool res = LLUICtrl::addChild(child, tab_group);
+
+	if(DD_HEADER_NAME != child->getName())
+	{
+		if(!mCollapsible)
+			setDisplayChildren(true);
+		else
+			setDisplayChildren(getDisplayChildren());	
+	}
+
+	return res;
+}
+
+void LLAccordionCtrlTab::setAccordionView(LLView* panel)
+{
+	addChild(panel,0);
+}
+
+
+LLView*	LLAccordionCtrlTab::getAccordionView()
+{
+	for(child_list_const_iter_t it = getChildList()->begin(); 
+		getChildList()->end() != it; ++it)
+	{
+		LLView* child = *it;
+		if(DD_HEADER_NAME == child->getName())
+			continue;
+		if(!child->getVisible())
+			continue;
+		return child;
+	}
+	return NULL;
+}
+
+
+S32 LLAccordionCtrlTab::getHeaderHeight()
+{
+	return mHeaderVisible?HEADER_HEIGHT:0; 
+}
+
+void LLAccordionCtrlTab::setHeaderVisible(bool value) 
+{
+	if(mHeaderVisible == value)
+		return;
+	mHeaderVisible = value;
+	if(mHeader)
+		mHeader->setVisible(value);
+	reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+};
+
+//vurtual
+BOOL LLAccordionCtrlTab::postBuild()
+{
+	mHeader->setVisible(mHeaderVisible);
+	return LLUICtrl::postBuild();
+}
+bool	LLAccordionCtrlTab::notifyChildren	(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "store_state")
+		{
+			storeOpenCloseState();
+			return true;
+		}
+		if(str_action == "restore_state")
+		{
+			restoreOpenCloseState();
+			return true;
+		}
+	}	
+	return LLUICtrl::notifyChildren(info);
+}
+
+S32	LLAccordionCtrlTab::notifyParent(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "size_changes")
+		{
+			//
+			S32 height = info["height"];
+			height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom();
+			
+			mExpandedHeight = height;
+			
+			if(isExpanded())
+			{
+				LLRect panel_rect = getRect();
+				panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height);
+				reshape(getRect().getWidth(),height);
+				setRect(panel_rect);
+			}
+			
+			//LLAccordionCtrl should rearrange accodion tab if one of accordion change its size
+			getParent()->notifyParent(info);
+			return 1;
+		}
+		else if(str_action == "select_prev") 
+		{
+			showAndFocusHeader();
+			return 1;
+		}
+	}
+	return LLUICtrl::notifyParent(info);
+}
+
+S32 LLAccordionCtrlTab::notify(const LLSD& info)
+{
+	if(info.has("action"))
+	{
+		std::string str_action = info["action"];
+		if(str_action == "select_first")
+		{
+			showAndFocusHeader();
+			return 1;
+		}
+		else if( str_action == "select_last" )
+		{
+			if(getDisplayChildren() == false)
+			{
+				showAndFocusHeader();
+			}
+			else
+			{
+				LLView* view = getAccordionView();
+				if(view)
+					view->notify(LLSD().with("action","select_last"));
+			}
+		}
+	}
+	return 0;
+}
+
+BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+	LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);	
+	if( !header->hasFocus() )
+		return LLUICtrl::handleKey(key, mask, called_from_parent);
+
+	if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE)
+	{
+		if(getDisplayChildren() == false)
+		{
+			changeOpenClose(getDisplayChildren());
+			return TRUE;
+		}
+	}
+	if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE)
+	{
+		if(getDisplayChildren() == true)
+		{
+			changeOpenClose(getDisplayChildren());
+			return TRUE;
+		}
+	}
+
+	if ( key == KEY_DOWN && mask == MASK_NONE)
+	{
+		//if collapsed go to the next accordion
+		if(getDisplayChildren() == false)
+			//we processing notifyParent so let call parent directly
+			getParent()->notifyParent(LLSD().with("action","select_next"));
+		else
+		{
+			getAccordionView()->notify(LLSD().with("action","select_first"));
+		}
+		return TRUE;
+	}
+
+	if ( key == KEY_UP && mask == MASK_NONE)
+	{
+		//go to the previous accordion
+
+		//we processing notifyParent so let call parent directly
+		getParent()->notifyParent(LLSD().with("action","select_prev"));
+		return TRUE;
+	}
+
+	return LLUICtrl::handleKey(key, mask, called_from_parent);
+}
+
+void LLAccordionCtrlTab::showAndFocusHeader()
+{
+	LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);	
+	header->setFocus(true);
+
+	LLRect screen_rc;
+	LLRect selected_rc = header->getRect();
+	localRectToScreen(selected_rc, &screen_rc);
+	notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
+
+}
+void    LLAccordionCtrlTab::storeOpenCloseState()
+{
+	if(mWasStateStored)
+		return;
+	mStoredOpenCloseState = getDisplayChildren();
+	mWasStateStored = true;
+}
+void   LLAccordionCtrlTab::restoreOpenCloseState()
+{
+	if(!mWasStateStored)
+		return;
+	if(getDisplayChildren() != mStoredOpenCloseState)
+	{
+		changeOpenClose(getDisplayChildren());
+	}
+	mWasStateStored = false;
+}
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
new file mode 100644
index 0000000000000000000000000000000000000000..b200d43438b5e2f4920a51a95965075a9a90c312
--- /dev/null
+++ b/indra/llui/llaccordionctrltab.h
@@ -0,0 +1,191 @@
+/** 
+ * @file LLAccordionCtrlTab.h
+ * @brief Collapsible box control implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * 
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCORDIONCTRLTAB_H_
+#define LL_ACCORDIONCTRLTAB_H_
+
+#include <string>
+#include "llrect.h"
+
+class LLUICtrl;
+class LLUICtrlFactory;
+class LLUIImage;
+class LLButton;
+class LLTextBox;
+
+
+
+// LLAccordionCtrlTab is a container for other controls. 
+// It has a Header, by clicking on which hosted controls are shown or hidden.
+// When hosted controls are show - LLAccordionCtrlTab is expanded.
+// When hosted controls are hidden - LLAccordionCtrlTab is collapsed.
+
+class LLAccordionCtrlTab : public LLUICtrl
+{
+// Interface
+public:
+
+	struct Params 
+	 : public LLInitParam::Block<Params, LLUICtrl::Params>
+	{
+		Optional<bool>			display_children, //expanded or collapsed after initialization
+								collapsible;
+
+		Optional<std::string>	title;
+
+		Optional<S32>			header_height,
+								min_width,
+								min_height;
+
+		// Overlay images (arrows on the left)
+		Mandatory<LLUIImage*>	header_expand_img,
+								header_expand_img_pressed,
+								header_collapse_img,
+								header_collapse_img_pressed;
+
+		// Background images for the accordion tabs
+		Mandatory<LLUIImage*>	header_image,
+								header_image_over,
+								header_image_pressed,
+								header_image_focused;
+
+		Optional<LLUIColor>		header_bg_color,
+								header_text_color,
+								dropdown_bg_color;
+
+		Optional<bool>			header_visible;
+
+		Optional<S32>			padding_left;
+		Optional<S32>			padding_right;
+		Optional<S32>			padding_top;
+		Optional<S32>			padding_bottom;
+
+		Params();
+	};
+
+	typedef LLDefaultChildRegistry child_registry_t;
+
+	virtual ~LLAccordionCtrlTab();
+	
+	// Registers callback for expand/collapse events.
+	boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb);
+
+	// Changes expand/collapse state
+	virtual void setDisplayChildren(bool display);
+
+	// Returns expand/collapse state
+	virtual bool getDisplayChildren() const {return mDisplayChildren;};
+
+	//set LLAccordionCtrlTab panel
+	void		setAccordionView(LLView* panel);
+	LLView*		getAccordionView();
+
+	bool getCollapsible() {return mCollapsible;};
+
+	void setCollapsible(bool collapsible) {mCollapsible = collapsible;};
+	void changeOpenClose(bool is_open);
+
+	void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;};
+
+	virtual BOOL postBuild();
+
+	S32	notifyParent(const LLSD& info);
+	S32 notify(const LLSD& info);
+	bool notifyChildren(const LLSD& info);
+
+	void    storeOpenCloseState		();
+	void    restoreOpenCloseState	();
+
+protected:
+	LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&);
+	friend class LLUICtrlFactory;
+
+// Overrides
+public:
+
+	// Call reshape after changing size
+	virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+	// Changes expand/collapse state and triggers expand/collapse callbacks
+	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+
+	virtual bool addChild(LLView* child, S32 tab_group);
+
+	bool isExpanded() { return mDisplayChildren; }
+
+	S32 getHeaderHeight();
+
+	// Min size functions
+
+	void setHeaderVisible(bool value);
+
+	bool getHeaderVisible() { return mHeaderVisible;}
+
+	S32 mExpandedHeight; // Height of expanded ctrl.
+						 // Used to restore height after expand.
+
+	S32	getPaddingLeft() const { return mPaddingLeft;}
+	S32	getPaddingRight() const { return mPaddingRight;}
+	S32	getPaddingTop() const { return mPaddingTop;}
+	S32	getPaddingBottom() const { return mPaddingBottom;}
+
+	void showAndFocusHeader();
+
+private:
+
+	
+
+	class LLAccordionCtrlTabHeader;
+	LLAccordionCtrlTabHeader* mHeader; //Header
+
+	bool mDisplayChildren; //Expanded/collapsed
+	bool mCollapsible;
+	bool mHeaderVisible;
+
+	bool mCanOpenClose;
+
+	S32	mPaddingLeft;
+	S32	mPaddingRight;
+	S32	mPaddingTop;
+	S32	mPaddingBottom;
+
+	bool mStoredOpenCloseState;
+	bool mWasStateStored;
+
+
+	LLUIColor mDropdownBGColor;
+};
+
+#endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8918fc301893315dc178ac5868a64052f2c2bc87..62cb8380c08ab49a9667fcde2c37443ae68a56e3 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -63,8 +63,6 @@ include_directories(
     )
 
 set(viewer_SOURCE_FILES
-    llaccordionctrl.cpp
-    llaccordionctrltab.cpp
     llagent.cpp
     llagentaccess.cpp
     llagentdata.cpp
@@ -569,8 +567,6 @@ endif (LINUX)
 set(viewer_HEADER_FILES
     CMakeLists.txt
     ViewerInstall.cmake
-    llaccordionctrl.h
-    llaccordionctrltab.h
     llagent.h
     llagentaccess.h
     llagentdata.h