diff --git a/code/nel/include/nel/gui/ctrl_scroll.h b/code/nel/include/nel/gui/ctrl_scroll.h
new file mode 100644
index 000000000..c20e41e4e
--- /dev/null
+++ b/code/nel/include/nel/gui/ctrl_scroll.h
@@ -0,0 +1,200 @@
+// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
+// Copyright (C) 2010  Winch Gate Property Limited
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program 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 Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#ifndef RZ_CTRL_SCROLL_H
+#define RZ_CTRL_SCROLL_H
+
+#include "nel/misc/types_nl.h"
+#include "nel/gui/ctrl_scroll_base.h"
+
+
+namespace NLGUI
+{
+
+	/**
+	 * Class handling scollbar function
+	 * \author Matthieu 'TrapII' Besson
+	 * \author Nevrax France
+	 * \date 2002
+	 */
+	class CCtrlScroll : public CCtrlScrollBase, public NLMISC::ICDBNode::IPropertyObserver
+	{
+
+	public:
+		DECLARE_UI_CLASS( CCtrlScroll )
+		CCtrlScroll(const TCtorParam &param);
+		~CCtrlScroll();
+
+
+		virtual bool parse(xmlNodePtr cur, CInterfaceGroup * parentGroup);
+
+		virtual void updateCoords();
+		virtual void draw();
+		virtual bool handleEvent (const NLGUI::CEventDescriptor &event);
+
+		void	setTarget (CInterfaceGroup *pIG);
+		// Return the delta value the track has moved
+		sint32	moveTrackX (sint32 dx);
+		sint32	moveTrackY (sint32 dy);
+
+		/** Move the Target Ofs with a Delta, and recompute TrackPos from this Ofs.
+		 *	Useful for finer controled group scrolling when the list is very big (with mouseWheel or scroll buttons)
+		 */
+		void	moveTargetX (sint32 dx);
+		void	moveTargetY (sint32 dy);
+
+		void	setAlign (sint32 nAlign) { _Aligned = nAlign; }
+		// invert the factor for target
+		void	setInverted(bool invert) { _Inverted = invert; }
+
+		void	setTextureBottomOrLeft	(const std::string &txName);
+		void	setTextureMiddle		(const std::string &txName);
+		void	setTextureTopOrRight	(const std::string &txName);
+
+		void	setTextureBottomOrLeft	(sint32 txid) { _TxIdB = txid; }
+		void	setTextureMiddle		(sint32 txid) { _TxIdM = txid; }
+		void	setTextureMiddleTile	(uint8 tile) { _TileM = tile; } // 0 - not tiled (1 BL) (2 BR) (3 TL) (4 TR)
+		void	setTextureTopOrRight	(sint32 txid) { _TxIdT = txid; }
+
+		// number scroller
+		sint32	getValue() const { return _IsDBLink ? _DBLink.getSInt32() : _Value; }
+		// NB: the value is clamped (see setMinMax) and stepped (see setStepValue())
+		void	setValue(sint32 value);
+		void	setMinMax(sint32 nMin, sint32 nMax) { _Min = nMin; _Max = nMax; }
+		void	setStepValue(uint32 step) { _StepValue= step; }
+
+		void	setTrackPos(sint32 pos);
+		sint32	getTrackPos() const { return _TrackPos; }
+		sint32	getTrackSize() const { return _TrackSize; }
+		// dummy set for track size (forlua export)
+		void	setTrackSize(sint32 /* trackSize */) { throw  NLMISC::Exception("TrackSize is read-only"); }
+
+
+		void	setFrozen (bool state);
+		bool	getFrozen () const { return _Frozen; }
+
+		int luaSetTarget(CLuaState &ls);
+		int luaEnsureVisible(CLuaState &ls);
+
+		// name
+		void			setName(const std::string & val) {_Name = val;}
+		std::string		getName() const {return _Name;}
+
+		// max
+		void			setMax(sint32 max) {_Max = max;}
+		sint32			getMax() const {return _Max;}
+
+		REFLECT_EXPORT_START(CCtrlScroll, CCtrlScrollBase)
+			REFLECT_LUA_METHOD("setTarget", luaSetTarget)
+			REFLECT_LUA_METHOD("ensureVisible", luaEnsureVisible);
+			REFLECT_SINT32("value", getValue, setValue);
+			REFLECT_SINT32("trackPos", getTrackPos, setTrackPos);
+			REFLECT_SINT32("trackSize", getTrackSize, setTrackSize);
+			REFLECT_STRING("name", getName, setName);
+			REFLECT_SINT32("max", getMax, setMax);
+		REFLECT_EXPORT_END
+
+		/** Ensure that a child element be visible into the frame through which
+		  * its parent group is displayed.
+		  * Example : Had we a list of items for which we want some item 'itemPtr' to have its top position
+		  * matching the middle of the list, we would do :
+		  * this->ensureVisible(itemPtr, Hotspot_Tx, Hotspot_Mx);
+		  *
+		  * The scrollbar will be moved accordingly.
+		  */
+		void ensureVisible(CInterfaceElement *childElement, THotSpot childHotSpot, THotSpot parentHotSpot);
+
+
+	protected:
+
+		CInterfaceProperty	_DBLink;	// If this is a value scroller we can link it with db
+		sint32				_Value;		// Or we can use a normal value
+		sint32				_InitialValue;
+
+		sint32 _Min, _Max;
+		std::string _AHOnScroll;
+		std::string _AHOnScrollParams;
+		//
+		std::string _AHOnScrollEnd;
+		std::string _AHOnScrollEndParams;
+		//
+		//
+		std::string _AHOnScrollCancel;
+		std::string _AHOnScrollCancelParams;
+
+
+		sint32 _Aligned; // 0-Top 1-Bottom 2-Left 3-Right
+
+		sint32 _TrackDispPos;
+		sint32 _TrackPos;
+		sint32 _TrackSize;
+		sint32 _TrackSizeMin;
+
+		sint32 _MouseDownOffsetX;
+		sint32 _MouseDownOffsetY;
+
+		sint32 _TxIdB; // Same as Left if Horizontal sb
+		sint32 _TxIdM;
+		sint32 _TxIdT; // Same as Right if Horizontal sb
+
+		uint8	_TileM;
+
+		sint32 _LastTargetHReal;
+		sint32 _LastTargetMaxHReal;
+		sint32 _LastTargetOfsY;
+		sint32 _LastTargetWReal;
+		sint32 _LastTargetMaxWReal;
+		sint32 _LastTargetOfsX;
+
+		bool	_Vertical   : 1; // true if vertical track bar
+		bool	_IsDBLink   : 1;
+		bool	_ObserverOn : 1;
+		bool    _Inverted   : 1;
+		bool    _MouseDown  : 1;
+		bool	_CallingAH  : 1;
+		bool	_Cancelable : 1; // true if the slider may be cancelled when pressed on the mouse right button
+		bool	_Frozen		: 1;
+
+		// For Target Scroller only: the target offset step in pixel.
+		sint32	_TargetStepX;
+		sint32	_TargetStepY;
+
+		// For Value Scroller only: indicate the step the scroll bar has. 0 or 1 means no step
+		uint32	_StepValue;
+
+		// Slider's name
+		std::string _Name;
+
+		void	computeTargetOfsFromPos();
+
+		// from IPropertyObserver
+		virtual void update(NLMISC::ICDBNode *node);
+
+		// step the value, and clamp it
+		void	normalizeValue(sint32 &value);
+
+		void runAH(const std::string &name, const std::string &params);
+
+	};
+}
+
+#endif // RZ_CTRL_SCROLL_H
+
+/* End of ctrl_scroll.h */
+
+
diff --git a/code/nel/include/nel/gui/group_submenu_base.h b/code/nel/include/nel/gui/group_submenu_base.h
new file mode 100644
index 000000000..9489109f8
--- /dev/null
+++ b/code/nel/include/nel/gui/group_submenu_base.h
@@ -0,0 +1,48 @@
+// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
+// Copyright (C) 2010  Winch Gate Property Limited
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program 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 Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef GROUP_SUBMENU_BASE
+#define GROUP_SUBMENU_BASE
+
+#include "nel/gui/group_frame.h"
+
+namespace NLGUI
+{
+
+	class CGroupSubMenuBase : public CGroupFrame
+	{
+	public:
+		DECLARE_UI_CLASS( CGroupSubMenuBase )
+
+		CGroupSubMenuBase( const TCtorParam &param );
+		~CGroupSubMenuBase();
+
+		virtual void openSubMenu( sint32 nb );
+		virtual void hideSubMenus();
+
+		REFLECT_EXPORT_START( CGroupSubMenuBase, CGroupFrame )
+		REFLECT_EXPORT_END
+
+	protected:
+
+	private:
+
+	};
+
+}
+
+#endif
+
diff --git a/code/nel/include/nel/gui/widget_manager.h b/code/nel/include/nel/gui/widget_manager.h
index a5a7b45b8..1c15ac357 100644
--- a/code/nel/include/nel/gui/widget_manager.h
+++ b/code/nel/include/nel/gui/widget_manager.h
@@ -20,6 +20,9 @@
 
 #include <string>
 #include <vector>
+#include <list>
+#include "nel/misc/smart_ptr.h"
+#include "nel/misc/rgba.h"
 #include "nel/misc/types_nl.h"
 #include "nel/gui/interface_common.h"
 
diff --git a/code/nel/src/gui/ctrl_scroll.cpp b/code/nel/src/gui/ctrl_scroll.cpp
new file mode 100644
index 000000000..597ccc3cd
--- /dev/null
+++ b/code/nel/src/gui/ctrl_scroll.cpp
@@ -0,0 +1,1062 @@
+// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
+// Copyright (C) 2010  Winch Gate Property Limited
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program 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 Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "nel/gui/widget_manager.h"
+#include "nel/gui/action_handler.h"
+#include "nel/gui/interface_group.h"
+#include "nel/gui/view_renderer.h"
+#include "nel/gui/ctrl_scroll.h"
+#include "nel/misc/xml_auto_ptr.h"
+#include "nel/gui/group_submenu_base.h"
+#include "nel/gui/lua_ihm.h"
+
+using namespace NLMISC;
+using namespace std;
+
+NLMISC_REGISTER_OBJECT(CViewBase, CCtrlScroll, std::string, "scroll");
+
+namespace NLGUI
+{
+
+	// ------------------------------------------------------------------------------------------------
+	CCtrlScroll::CCtrlScroll(const TCtorParam &param)
+	:	CCtrlScrollBase(param)
+	{
+		_Vertical = true;
+		_Aligned = 1;
+		_TrackPos = 0;
+		_TrackDispPos = 0;
+		_TrackSize = _TrackSizeMin = 16;
+		_Min = 0;
+		_Max = 100;
+		_Value = 0;
+		_InitialValue = 0;
+		_MouseDown = false;
+		_CallingAH = false;
+		_Cancelable = false;
+		_Target = NULL;
+		_Inverted = false;
+		_IsDBLink = false;
+		_LastTargetHReal = 0;
+		_LastTargetMaxHReal = 0;
+		_LastTargetWReal = 0;
+		_LastTargetMaxWReal = 0;
+		_LastTargetOfsX = 0;
+		_LastTargetOfsY = 0;
+		_ObserverOn = true;
+		_TargetStepX = 1;
+		_TargetStepY = 1;
+		_StepValue = 0;
+		_TileM = false;
+		_Frozen = false;
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::runAH(const std::string &name, const std::string &params)
+	{
+		if (name.empty()) return;
+		if (_CallingAH) return; // avoid infinite loop
+		_CallingAH = true;
+		CAHManager::getInstance()->runActionHandler(name, this, params);
+		_CallingAH = false;
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	CCtrlScroll::~CCtrlScroll()
+	{
+		if (_IsDBLink)
+		{
+			ICDBNode::CTextId textId;
+			_DBLink.getNodePtr()->removeObserver(this, textId);
+		}
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	bool CCtrlScroll::parse(xmlNodePtr node, CInterfaceGroup * parentGroup)
+	{
+		if (!CCtrlBase::parse(node, parentGroup))
+			return false;
+
+		CXMLAutoPtr prop;
+		// Read textures
+		prop = (char*) xmlGetProp( node, (xmlChar*)"tx_bottomleft" );
+		if(prop) setTextureBottomOrLeft(string((const char*)prop));
+		else setTextureBottomOrLeft ("w_scroll_l0_b.tga");
+
+		prop = (char*) xmlGetProp( node, (xmlChar*)"tx_middle" );
+		if(prop)	setTextureMiddle(string((const char*)prop));
+		else setTextureMiddle ("w_scroll_l0_m.tga");
+
+		prop = (char*) xmlGetProp( node, (xmlChar*)"tx_topright" );
+		if(prop) setTextureTopOrRight(string((const char*)prop));
+		else setTextureTopOrRight ("w_scroll_l0_t.tga");
+
+		// Read properties
+		prop = (char*) xmlGetProp( node, (xmlChar*)"vertical" );
+		if (prop) _Vertical = convertBool((const char*)prop);
+
+		prop = (char*) xmlGetProp (node, (xmlChar*)"align");
+		_Aligned = 1;
+		if (prop)
+		{
+			if (stricmp(prop, "T") == 0) _Aligned = 0;
+			else if (stricmp(prop, "B") == 0) _Aligned = 1;
+			else if (stricmp(prop, "L") == 0) _Aligned = 2;
+			else if (stricmp(prop, "R") == 0) _Aligned = 3;
+		}
+
+		prop = (char*) xmlGetProp( node, (xmlChar*)"min" );
+		if (prop) fromString((const char*)prop, _Min);
+
+		prop = (char*) xmlGetProp( node, (xmlChar*)"max" );
+		if (prop) fromString((const char*)prop, _Max);
+
+		prop = (char*) xmlGetProp( node, (xmlChar*)"value" );
+		if (prop)
+		{
+			if ( isdigit(*prop) || *prop=='-')
+			{
+				_IsDBLink = false;
+				fromString((const char*)prop, _Value);
+			}
+			else
+			{
+				_IsDBLink = true;
+				_DBLink.link(prop);
+				ICDBNode::CTextId textId;
+				_DBLink.getNodePtr()->addObserver(this, textId);
+
+			}
+		}
+
+		prop = (char*) xmlGetProp( node, (xmlChar*)"tracksize" );
+		if (prop) fromString((const char*)prop, _TrackSize);
+
+		// Read Action handlers
+		prop = (char*) xmlGetProp( node, (xmlChar*)"onscroll" );
+		if (prop)	_AHOnScroll = NLMISC::strlwr(prop);
+		prop = (char*) xmlGetProp( node, (xmlChar*)"params" );
+		if (prop)	_AHOnScrollParams = string((const char*)prop);
+		//
+		prop = (char*) xmlGetProp( node, (xmlChar*)"onscrollend" );
+		if (prop)	_AHOnScrollEnd = NLMISC::strlwr(prop);
+		prop = (char*) xmlGetProp( node, (xmlChar*)"end_params" );
+		if (prop)	_AHOnScrollEndParams = string((const char*)prop);
+		//
+		prop = (char*) xmlGetProp( node, (xmlChar*)"onscrollcancel" );
+		if (prop)	_AHOnScrollCancel = NLMISC::strlwr(prop);
+		prop = (char*) xmlGetProp( node, (xmlChar*)"cancel_params" );
+		if (prop)	_AHOnScrollCancelParams = string((const char*)prop);
+
+
+		// auto-target
+		prop = (char*) xmlGetProp( node, (xmlChar*)"target" );
+		if (prop)
+		{
+			CInterfaceGroup	*group = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(prop));
+			if(group == NULL)
+				group = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(this->getId(), prop));
+
+			if(group != NULL)
+				setTarget (group);
+		}
+
+
+		// auto-step
+		prop = (char*) xmlGetProp( node, (xmlChar*)"target_stepx" );
+		if(prop)	fromString((const char*)prop, _TargetStepX);
+		prop = (char*) xmlGetProp( node, (xmlChar*)"target_stepy" );
+		if(prop)	fromString((const char*)prop, _TargetStepY);
+		_TargetStepX= max((sint32)1, _TargetStepX);
+		_TargetStepY= max((sint32)1, _TargetStepY);
+
+		// Scroll Step
+		prop = (char*) xmlGetProp( node, (xmlChar*)"step_value" );
+		if(prop)	fromString((const char*)prop, _StepValue);
+
+		prop = (char*) xmlGetProp( node, (xmlChar*)"cancelable" );
+		if (prop) _Cancelable = convertBool(prop);
+
+		prop= (char*) xmlGetProp (node, (xmlChar*)"frozen");
+		_Frozen = false;
+		if (prop)
+			_Frozen = convertBool(prop);
+
+
+		return true;
+	}
+
+	// ------------------------------------------------------------------------------------------------
+
+	int CCtrlScroll::luaSetTarget(CLuaState &ls)
+	{
+		const char *funcName = "setTarget";
+		CLuaIHM::checkArgCount(ls, funcName, 1);
+		CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
+		std::string targetId = ls.toString(1);
+
+		CInterfaceGroup	*group = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(targetId));
+		if(group != NULL)
+		{
+			setTarget (group);
+		}
+
+		return 0;
+	}
+
+	void CCtrlScroll::updateCoords()
+	{
+		if (_Target)
+		{
+			// update only if visible
+			if (_Target->getActive())
+			{
+				CViewRenderer &rVR = *CViewRenderer::getInstance();
+				sint32 w, h;
+				rVR.getTextureSizeFromId (_TxIdB, w, h);
+
+				if (_Vertical)
+				{
+					_W = w;
+					_H = _Target->getMaxHReal();
+				}
+				else
+				{
+					_W = _Target->getMaxWReal();
+					_H = h;
+				}
+
+				CCtrlBase::updateCoords ();
+				if (_Vertical)
+				{
+					if(_Target->getHReal()!=_LastTargetHReal || _Target->getMaxHReal()!=_LastTargetMaxHReal ||
+					   _Target->getOfsY() != _LastTargetOfsY
+					  )
+					{
+						_LastTargetHReal= _Target->getHReal();
+						_LastTargetMaxHReal= _Target->getMaxHReal();
+						_LastTargetOfsY = _Target->getOfsY();
+
+						// Activate only if needed
+						setActive(_Target->getHReal() > _Target->getMaxHReal());
+						CCtrlBase::updateCoords();
+
+						// Calculate size of the track button
+						if ((_Target->getHReal() <= _Target->getMaxHReal()) || (_Target->getHReal() == 0))
+						{
+							_TrackSize = _Target->getMaxHReal();
+						}
+						else
+						{
+							float factor = (float)_Target->getMaxHReal() / (float)_Target->getHReal();
+							factor = _TrackSizeMin + factor * (this->getHReal() - _TrackSizeMin);
+							_TrackSize = (sint32)factor;
+						}
+						// Calculate pos of the track button
+						if (_Target->getHReal() <= _Target->getMaxHReal())
+						{
+							if (_Aligned == 1) // BOTTOM
+								_TrackPos = 0;
+							else // TOP
+								_TrackPos = getHReal()-_TrackSize;
+						}
+						else
+						{
+							if (_Aligned == 1) // BOTTOM
+							{
+								float factor = ((float)_Target->getHReal() - (float)_Target->getMaxHReal());
+								factor = -(float)_Target->getOfsY() / factor;
+								if (factor < 0.0f) factor = 0.0f;
+								if (factor > 1.0f) factor = 1.0f;
+								factor = factor * (getHReal()-_TrackSize);
+								_TrackPos = (sint32)factor;
+							}
+							else // TOP
+							{
+								float factor = ((float)_Target->getHReal() - (float)_Target->getMaxHReal());
+								factor = (float)_Target->getOfsY() / factor;
+								if (factor < 0.0f) factor = 0.0f;
+								if (factor > 1.0f) factor = 1.0f;
+								sint32 hreal = getHReal();
+								factor = (1.0f-factor) * (hreal - _TrackSize);
+								_TrackPos = (sint32)factor;
+							}
+						}
+
+						// invalidate coords.
+						computeTargetOfsFromPos();
+					}
+				}
+				else // Horizontal Tracker
+				{
+					if(_Target->getWReal()!=_LastTargetWReal || _Target->getMaxWReal()!=_LastTargetMaxWReal ||
+					   _Target->getOfsX() != _LastTargetOfsX)
+					{
+						_LastTargetWReal= _Target->getWReal();
+						_LastTargetMaxWReal= _Target->getMaxWReal();
+						_LastTargetOfsX = _Target->getOfsX();
+
+						// Activate only if needed
+						setActive(_Target->getWReal() > _Target->getMaxWReal());
+						CCtrlBase::updateCoords();
+
+						// Calculate size of the track button
+						if ((_Target->getWReal() <= _Target->getMaxWReal()) || (_Target->getWReal() == 0))
+						{
+							_TrackSize = _Target->getMaxWReal();
+						}
+						else
+						{
+							float factor = (float)_Target->getMaxWReal() / (float)_Target->getWReal();
+							factor = _TrackSizeMin + factor * (this->getWReal() - _TrackSizeMin);
+							_TrackSize = (sint32)factor;
+						}
+						// Calculate pos of the track button
+						if (_Target->getWReal() <= _Target->getMaxWReal())
+						{
+							if (_Aligned == 2) // LEFT
+								_TrackPos = 0;
+							else // RIGHT
+								_TrackPos = getWReal()-_TrackSize;
+						}
+						else
+						{
+							if (_Aligned == 2) // LEFT
+							{
+								float factor = ((float)_Target->getWReal() - (float)_Target->getMaxWReal());
+								factor = -(float)_Target->getOfsX() / factor;
+								if (factor < 0.0f) factor = 0.0f;
+								if (factor > 1.0f) factor = 1.0f;
+								factor = factor * (getWReal()-_TrackSize);
+								_TrackPos = (sint32)factor;
+							}
+							else // RIGHT
+							{
+								float factor = ((float)_Target->getWReal() - (float)_Target->getMaxWReal());
+								factor = (float)_Target->getOfsX() / factor;
+								if (factor < 0.0f) factor = 0.0f;
+								if (factor > 1.0f) factor = 1.0f;
+								sint32 hreal = getWReal();
+								factor = (1.0f-factor) * (hreal - _TrackSize);
+								_TrackPos = (sint32)factor;
+							}
+						}
+
+						// invalidate coords.
+						computeTargetOfsFromPos();
+					}
+				}
+			}
+			// reset cache
+			else
+			{
+				_LastTargetHReal= 0;
+				_LastTargetMaxHReal= 0;
+				_LastTargetWReal= 0;
+				_LastTargetMaxWReal= 0;
+				_LastTargetOfsX = 0;
+				_LastTargetOfsY = 0;
+				setActive(false);
+			}
+		}
+		else
+		{
+			CCtrlBase::updateCoords ();
+			if (_IsDBLink)
+				_Value = _DBLink.getSInt32();
+			if (_Vertical)
+			{
+				float factor;
+				if (_Aligned == 1) // BOTTOM
+					factor = ((float)_Value-_Min) / (_Max-_Min);
+				else // TOP
+					factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
+				factor *= (this->getHReal() - _TrackSize);
+
+				_TrackDispPos = (sint32)factor;
+			}
+			else
+			{
+				float factor;
+				if (_Aligned == 2) // LEFT
+					factor = ((float)_Value-_Min) / (_Max-_Min);
+				else // RIGHT
+					factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
+				factor *= (this->getWReal() - _TrackSize);
+
+				_TrackDispPos = (sint32)factor;
+			}
+		}
+		CCtrlBase::updateCoords ();
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::draw()
+	{
+		CViewRenderer &rVR = *CViewRenderer::getInstance();
+		CRGBA col = CWidgetManager::getInstance()->getGlobalColorForContent();
+
+		if (_Target)
+		{
+			if (_Vertical)
+			{
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackPos, _WReal, 4, 0, false, _TxIdB, col );
+				if (_TileM == 0)
+					rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, col );
+				else
+					rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal, _YReal+_TrackPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, _TileM-1, col );
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackPos+_TrackSize-4, _WReal, 4, 0, false, _TxIdT, col );
+			}
+			else
+			{
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackPos, _YReal, 4, _HReal, 0, false, _TxIdB, col );
+				if (_TileM == 0)
+					rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, col );
+				else
+					rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal+_TrackPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, _TileM-1, col );
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackPos+_TrackSize-4, _YReal, 4, _HReal, 0, false, _TxIdT, col );
+			}
+		}
+		else
+		{
+			if (_Vertical)
+			{
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackDispPos, _WReal, 4, 0, false, _TxIdB, col );
+				if (_TileM == 0)
+					rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackDispPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, col );
+				else
+					rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal, _YReal+_TrackDispPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, _TileM-1, col );
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackDispPos+_TrackSize-4, _WReal, 4, 0, false, _TxIdT, col );
+			}
+			else
+			{
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackDispPos, _YReal, 4, _HReal, 0, false, _TxIdB, col );
+				if (_TileM == 0)
+					rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackDispPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, col );
+				else
+					rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal+_TrackDispPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, _TileM-1, col );
+				rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackDispPos+_TrackSize-4, _YReal, 4, _HReal, 0, false, _TxIdT, col );
+			}
+		}
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	bool CCtrlScroll::handleEvent (const NLGUI::CEventDescriptor &event)
+	{
+		if (CCtrlBase::handleEvent(event)) return true;
+		if (!_Active || _Frozen)
+			return false;
+		if (event.getType() == NLGUI::CEventDescriptor::mouse)
+		{
+			const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
+			if ((CWidgetManager::getInstance()->getCapturePointerLeft() != this) &&
+				(!((eventDesc.getX() >= _XReal) &&
+				(eventDesc.getX() < (_XReal + _WReal))&&
+				(eventDesc.getY() > _YReal) &&
+				(eventDesc.getY() <= (_YReal+ _HReal)))))
+				return false;
+
+			if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown)
+			{
+				_MouseDown = true;
+				_InitialValue = getValue();
+				if (!_Target)
+					_TrackPos = _TrackDispPos;
+				_MouseDownOffsetX = eventDesc.getX() - (getXReal() + (_Vertical ? 0 : _TrackPos));
+				_MouseDownOffsetY = eventDesc.getY() - (getYReal() + (_Vertical ? _TrackPos : 0));
+
+				// if target is a menu, hidde its sub menus
+				if(_Target && _Target->getParent())
+				{
+					CGroupSubMenuBase *menu = dynamic_cast<CGroupSubMenuBase*>(_Target->getParent());
+					if(menu)
+						menu->hideSubMenus();
+				}
+				return true;
+			}
+			if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup)
+			{
+				_MouseDown = false;
+				runAH(_AHOnScrollEnd, _AHOnScrollEndParams.empty() ? _AHOnScrollParams : _AHOnScrollEndParams); // backward compatibility
+				return true;
+			}
+			if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown && _MouseDown && _Cancelable)
+			{
+				_MouseDown = false;
+				setValue(_InitialValue);
+				runAH(_AHOnScrollCancel, _AHOnScrollCancelParams); // backward compatibility
+				return true;
+			}
+			if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousemove)
+			{
+				if (_MouseDown)
+				{
+					sint32 dx = eventDesc.getX() - (getXReal() + (_Vertical ? 0 : _TrackPos) + _MouseDownOffsetX);
+					sint32 dy = eventDesc.getY() - (getYReal() + (_Vertical ? _TrackPos : 0 ) + _MouseDownOffsetY);
+					if (dx != 0) moveTrackX (dx);
+					if (dy != 0) moveTrackY (dy);
+				}
+				return true;
+			}
+			if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel && _Vertical)
+			{
+				moveTrackY (eventDesc.getWheel() * 12);
+				return true;
+			}
+		}
+		return false;
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::setTarget (CInterfaceGroup *pIG)
+	{
+		_Target = pIG;
+
+		if (_Vertical)
+		{
+			if (_Target->getPosRef()&Hotspot_Tx)
+				_Aligned = 0;
+			else
+				_Aligned = 1;
+
+			if (_Target->getPosRef()&Hotspot_Tx)
+				_Inverted = true;
+			else
+				_Inverted = true;
+		}
+		else
+		{
+			if (_Target->getPosRef()&Hotspot_xL)
+				_Aligned = 2;
+			else
+				_Aligned = 3;
+
+			if (_Target->getPosRef()&Hotspot_xL)
+				_Inverted = true;
+			else
+				_Inverted = true;
+		}
+	}
+	// ------------------------------------------------------------------------------------------------
+	sint32 CCtrlScroll::moveTrackX (sint32 dx)
+	{
+		if (_Vertical)
+			return 0;
+		if ((getWReal()-_TrackSize) <= 0)
+			return 0;
+
+		sint32 newtpos;
+		sint32 tpos = _TrackPos;
+		sint32 tsize = _TrackSize;
+
+		// Limit the scroller to the defined area
+		newtpos = tpos + dx;
+		if (newtpos < 0) newtpos = 0;
+		if (newtpos > (getWReal()-tsize)) newtpos = (getWReal()-tsize);
+		dx = newtpos - tpos;
+
+		if (_Target)
+		{
+			_TrackPos = newtpos;
+
+			computeTargetOfsFromPos();
+		}
+		else // This is a number scroller
+		{
+			float factor = (float)(_Max - _Min);
+
+			if (_Aligned == 2) // LEFT
+				factor = -factor * newtpos / (float)(getWReal()-tsize) - _Min;
+			else // RIGHT
+				factor = factor * (1.0f-(newtpos / (float)(getWReal()-tsize))) + _Min;
+
+			_TrackPos = newtpos;
+
+			if (_Aligned == 2) // LEFT
+				_Value = (sint32) (_Inverted ? factor : -factor);
+			else // RIGHT
+				_Value = (sint32) (_Inverted ? factor : -factor);
+
+			// step and clamp value
+			normalizeValue(_Value);
+
+			{
+				float factor;
+				if (_Aligned == 2) // LEFT
+					factor = ((float)_Value-_Min) / (_Max-_Min);
+				else // RIGHT
+					factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
+				factor *= (this->getWReal() - _TrackSize);
+
+				_TrackDispPos = (sint32)factor;
+			}
+
+			if (_IsDBLink)
+			{
+				_ObserverOn = false;
+				_DBLink.setSInt32 (_Value);
+				_ObserverOn = true;
+			}
+		}
+
+		// Launch the scroller event if any
+		runAH(_AHOnScroll, _AHOnScrollParams);
+
+		return dx;
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	sint32 CCtrlScroll::moveTrackY (sint32 dy)
+	{
+		if (!_Vertical)
+			return 0;
+		if ((getHReal()-_TrackSize) <= 0)
+			return 0;
+
+		sint32 newtpos;
+		sint32 tpos = _TrackPos;
+		sint32 tsize = _TrackSize;
+
+		// Limit the scroller to the defined area
+		newtpos = tpos + dy;
+		if (newtpos < 0) newtpos = 0;
+		if (newtpos > (getHReal()-tsize)) newtpos = (getHReal()-tsize);
+		dy = newtpos - tpos;
+
+		if (_Target)
+		{
+			_TrackPos = newtpos;
+
+			computeTargetOfsFromPos();
+		}
+		else // This is a number scroller
+		{
+			float factor = (float)(_Max - _Min);
+
+			if (_Aligned == 1) // BOTTOM
+				factor = -factor * newtpos / (float)(getHReal()-tsize) - _Min;
+			else // TOP
+				factor = factor * (1.0f-(newtpos / (float)(getHReal()-tsize))) + _Min;
+
+			_TrackPos = newtpos;
+
+			if (_Aligned == 1) // BOTTOM
+				_Value = (sint32) (_Inverted ? factor : -factor);
+			else // TOP
+				_Value = (sint32) (_Inverted ? factor : -factor);
+
+			// step and clamp value
+			normalizeValue(_Value);
+
+			{
+				float factor;
+				if (_Aligned == 1) // BOTTOM
+					factor = ((float)_Value-_Min) / (_Max-_Min);
+				else // TOP
+					factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
+				factor *= (this->getHReal() - _TrackSize);
+
+				_TrackDispPos = (sint32)factor;
+			}
+
+			if (_IsDBLink)
+			{
+				_ObserverOn = false;
+				_DBLink.setSInt32 (_Value);
+				_ObserverOn = true;
+			}
+		}
+
+		// Launch the scroller event if any
+		runAH(_AHOnScroll, _AHOnScrollParams);
+
+		return dy;
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::setTextureBottomOrLeft (const std::string &txName)
+	{
+		CViewRenderer &rVR = *CViewRenderer::getInstance();
+		_TxIdB = rVR.getTextureIdFromName(txName);
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::setTextureMiddle (const std::string &txName)
+	{
+		CViewRenderer &rVR = *CViewRenderer::getInstance();
+		_TxIdM = rVR.getTextureIdFromName(txName);
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::setTextureTopOrRight (const std::string &txName)
+	{
+		CViewRenderer &rVR = *CViewRenderer::getInstance();
+		_TxIdT = rVR.getTextureIdFromName(txName);
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::setValue(sint32 value)
+	{
+		normalizeValue(value);
+
+		if (_IsDBLink)
+		{
+			_ObserverOn = false;
+			_DBLink.setSInt32(value);
+			_ObserverOn = true;
+		}
+		else
+		{
+			_Value = value;
+		}
+		invalidateCoords();
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::setTrackPos(sint32 pos)
+	{
+		if (_Vertical)
+		{
+			moveTrackY(pos - _TrackPos);
+		}
+		else
+		{
+			moveTrackX(pos - _TrackPos);
+		}
+		invalidateCoords();
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::computeTargetOfsFromPos()
+	{
+		if(_Vertical)
+		{
+			float factor = ((float)_Target->getHReal() - (float)_Target->getMaxHReal());
+
+			if (_Aligned == 1) // BOTTOM
+				factor = -factor * _TrackPos / favoid0((float)(getHReal()-_TrackSize));
+			else // TOP
+				factor = factor * (1.0f-(_TrackPos / favoid0((float)(getHReal()-_TrackSize))));
+
+			// Compute Steped target
+			sint32	nexOfsY= (sint32) (_Inverted ? factor : -factor);
+			if(_TargetStepY>1)
+				nexOfsY= ((nexOfsY+_TargetStepY/2)/_TargetStepY) * _TargetStepY;
+			_Target->setOfsY (nexOfsY);
+			_LastTargetOfsY = nexOfsY;
+
+			// invalidate only XReal/YReal, doing only 1 pass
+			_Target->invalidateCoords(1);
+		}
+		else
+		{
+			float factor = ((float)_Target->getWReal() - (float)_Target->getMaxWReal());
+
+			if (_Aligned == 2) // LEFT
+				factor = -factor * _TrackPos / favoid0((float)(getWReal()-_TrackSize));
+			else // RIGHT
+				factor = factor * (1.0f-(_TrackPos / favoid0((float)(getWReal()-_TrackSize))));
+
+			// Compute Steped target
+			sint32	nexOfsX= (sint32) (_Inverted ? factor : -factor);
+			if(_TargetStepX>1)
+				nexOfsX= ((nexOfsX+_TargetStepX/2)/_TargetStepX) * _TargetStepX;
+			_Target->setOfsX (nexOfsX);
+			_LastTargetOfsX = nexOfsX;
+
+			// invalidate only XReal/YReal, doing only 1 pass
+			_Target->invalidateCoords(1);
+		}
+	}
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::update(ICDBNode * /* node */)
+	{
+		if (!_ObserverOn) return;
+		_Value = _DBLink.getSInt32();
+		// the value in the db changed
+		invalidateCoords(1);
+		if (_Target) _Target->invalidateCoords(1);
+	}
+
+
+	// ***************************************************************************
+	void	CCtrlScroll::moveTargetX (sint32 dx)
+	{
+		if(!_Target)
+			return;
+		sint32	maxWReal= _Target->getMaxWReal();
+		sint32	wReal= _Target->getWReal();
+		if(wReal <= maxWReal)
+			return;
+
+		// compute the new ofsX.
+		sint32	ofsX= _Target->getOfsX();
+		ofsX+= dx;
+		clamp(ofsX, 0, wReal-maxWReal);
+		_Target->setOfsX(ofsX);
+
+		// compute new trackPos.
+		if (_Aligned == 2) // LEFT
+		{
+			float factor = (float)(wReal-maxWReal);
+			factor = -(float)ofsX / factor;
+			clamp(factor, 0.f, 1.f);
+			factor = factor * (getWReal()-_TrackSize);
+			_TrackPos = (sint32)factor;
+		}
+		else // RIGHT
+		{
+			float factor = (float)(wReal-maxWReal);
+			factor = (float)ofsX / factor;
+			clamp(factor, 0.f, 1.f);
+			factor = (1.0f-factor) * (getWReal() - _TrackSize);
+			_TrackPos = (sint32)factor;
+		}
+
+		// invalidate only position. 1 pass is sufficient
+		invalidateCoords(1);
+	}
+
+	// ***************************************************************************
+	void	CCtrlScroll::moveTargetY (sint32 dy)
+	{
+		if(!_Target)
+			return;
+		sint32	maxHReal= _Target->getMaxHReal();
+		sint32	hReal= _Target->getHReal();
+		if(hReal <= maxHReal)
+			return;
+
+		// compute the new ofsY.
+		sint32	ofsY= _Target->getOfsY();
+		ofsY+= dy;
+
+		// compute new trackPos.
+		if (_Aligned == 1) // BOTTOM
+		{
+			clamp(ofsY, maxHReal - hReal, 0);
+			_Target->setOfsY(ofsY);
+			float factor = (float)(hReal-maxHReal);
+			factor = -(float)ofsY / factor;
+			clamp(factor, 0.f, 1.f);
+			factor = factor * (getHReal()-_TrackSize);
+			_TrackPos = (sint32)factor;
+		}
+		else // TOP
+		{
+			clamp(ofsY, 0, hReal-maxHReal);
+			_Target->setOfsY(ofsY);
+			float factor = (float)(hReal-maxHReal);
+			factor = (float)ofsY / factor;
+			clamp(factor, 0.f, 1.f);
+			factor = (1.0f-factor) * (getHReal() - _TrackSize);
+			_TrackPos = (sint32)factor;
+		}
+
+		// invalidate only position. 1 pass is sufficient
+		invalidateCoords(1);
+	}
+
+	// ***************************************************************************
+	void	CCtrlScroll::normalizeValue(sint32 &value)
+	{
+		// if, 0 no step
+		if(_StepValue==0 || _StepValue==1)
+			return;
+		// if interval is null, force min!
+		if(_Max==_Min)
+		{
+			value= _Min;
+			return;
+		}
+
+		// get range of possible position
+	//	sint32	size= _Max - _Min;
+
+		// step (round)
+		sint32	val= (value + (_StepValue/2) -_Min) / _StepValue;
+		val= _Min + val * _StepValue;
+		clamp(val, _Min, _Max);
+		value= val;
+	}
+
+	// ***************************************************************************
+	void CCtrlScroll::setFrozen (bool state)
+	{
+		_Frozen = state;
+		if (_Frozen)
+		{
+			_Value = 0;
+		}
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	int CCtrlScroll::luaEnsureVisible(CLuaState &ls)
+	{
+		const char *funcName = "ensureVisible";
+		CLuaIHM::checkArgCount(ls, funcName, 3);
+		CLuaIHM::checkArgTypeUIElement(ls, funcName, 1);
+		CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
+		CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
+		THotSpot	hs[2];
+		std::string hsStr[] = { ls.toString(2), ls.toString(3) };
+		//
+		for (uint hsIndex = 0; hsIndex < 2; ++ hsIndex)
+		{
+			if (_Vertical)
+			{
+				if (NLMISC::nlstricmp(hsStr[hsIndex], "T") == 0)
+				{
+					hs[hsIndex] = Hotspot_Tx;
+				}
+				else
+				if (NLMISC::nlstricmp(hsStr[hsIndex], "M") == 0)
+				{
+					hs[hsIndex] = Hotspot_Mx;
+				}
+				else
+				if (NLMISC::nlstricmp(hsStr[hsIndex], "B") == 0)
+				{
+					hs[hsIndex] = Hotspot_Bx;
+				}
+				else
+				{
+					CLuaIHM::fails(ls, "%s : couldn't parse hotspot for vertical scrollbar", funcName);
+				}
+			}
+			else
+			{
+				if (NLMISC::nlstricmp(hsStr[hsIndex], "L") == 0)
+				{
+					hs[hsIndex] = Hotspot_xL;
+				}
+				else
+				if (NLMISC::nlstricmp(hsStr[hsIndex], "M") == 0)
+				{
+					hs[hsIndex] = Hotspot_xM;
+				}
+				else
+				if (NLMISC::nlstricmp(hsStr[hsIndex], "R") == 0)
+				{
+					hs[hsIndex] = Hotspot_xR;
+				}
+				else
+				{
+					CLuaIHM::fails(ls, "%s : couldn't parse hotspot for horizontal scrollbar", funcName);
+				}
+			}
+		}
+		ensureVisible(CLuaIHM::getUIOnStack(ls, 1), hs[0], hs[1]);
+		return 0;
+	}
+
+
+	// ------------------------------------------------------------------------------------------------
+	void CCtrlScroll::ensureVisible(CInterfaceElement *childElement, THotSpot childHotSpot, THotSpot parentHotSpot)
+	{
+		if (!_Target) return; // not connected to a target yet
+		if (!childElement) return;
+		// compute corners of interest for enclosed element & enclosing group
+		sint32 childX, childY;
+		childElement->getCorner(childX, childY, childHotSpot);
+		if (_Vertical)
+		{
+			sint32	maxHReal= _Target->getMaxHReal();
+			sint32	hReal=	  _Target->getHReal();
+			if(hReal > maxHReal)
+			{
+				sint enclosingDY;
+				switch (parentHotSpot)
+				{
+					case Hotspot_Bx:
+						enclosingDY = maxHReal;
+					break;
+					case Hotspot_Mx:
+						enclosingDY = maxHReal / 2;
+					break;
+					case Hotspot_Tx:
+						enclosingDY = 0;
+					break;
+					default:
+						nlassert(0);
+					break;
+				}
+				if (_Aligned == 0)
+				{
+					// Top aligned case
+					sint32 offsetY = (_Target->getYReal() + _Target->getHReal() - childY) - enclosingDY;
+					NLMISC::clamp(offsetY, 0, hReal - maxHReal);
+					_Target->setOfsY(offsetY);
+					_Target->invalidateCoords();
+				}
+				else if (_Aligned == 1)
+				{
+					// Bottom aligned case
+					sint32 offsetY = (maxHReal - enclosingDY) - (childY - _Target->getYReal());
+					NLMISC::clamp(offsetY, maxHReal - hReal, 0);
+					_Target->setOfsY(offsetY);
+					_Target->invalidateCoords();
+				}
+			}
+			// else, ... fully visible (not occluded by parent group)
+		}
+		else
+		{
+			sint32	maxWReal= _Target->getMaxWReal();
+			sint32	wReal=	  _Target->getWReal();
+			if(wReal > maxWReal)
+			{
+				sint enclosingDX;
+				switch (parentHotSpot)
+				{
+					case Hotspot_xL:
+						enclosingDX = maxWReal;
+					break;
+					case Hotspot_xM:
+						enclosingDX = maxWReal / 2;
+					break;
+					case Hotspot_xR:
+						enclosingDX = 0;
+					break;
+					default:
+						nlassert(0);
+					break;
+				}
+				if (_Aligned == 3)
+				{
+					// right aligned case
+					sint32 offsetX = (_Target->getXReal() + _Target->getWReal() - childX) - enclosingDX;
+					NLMISC::clamp(offsetX, 0, wReal - maxWReal);
+					_Target->setOfsX(offsetX);
+					_Target->invalidateCoords();
+				}
+				else if (_Aligned == 2)
+				{
+					// Left aligned case
+					sint32 offsetX = (maxWReal - enclosingDX) - (childX - _Target->getXReal());
+					NLMISC::clamp(offsetX, maxWReal - wReal, 0);
+					_Target->setOfsX(offsetX);
+					_Target->invalidateCoords();
+				}
+			}
+			// else, ... fully visible (not occluded by parent group)
+		}
+	}
+}
+
diff --git a/code/nel/src/gui/group_submenu_base.cpp b/code/nel/src/gui/group_submenu_base.cpp
new file mode 100644
index 000000000..365f3f85e
--- /dev/null
+++ b/code/nel/src/gui/group_submenu_base.cpp
@@ -0,0 +1,47 @@
+// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
+// Copyright (C) 2010  Winch Gate Property Limited
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program 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 Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "nel/gui/group_submenu_base.h"
+
+namespace NLGUI
+{
+
+	CGroupSubMenuBase::CGroupSubMenuBase( const NLGUI::CViewBase::TCtorParam &param ) :
+	CGroupFrame( param )
+	{
+	}
+
+	CGroupSubMenuBase::~CGroupSubMenuBase()
+	{
+	}
+
+	void CGroupSubMenuBase::openSubMenu( sint32 nb )
+	{
+		// Necessary because it's supposed to be an abstract class,
+		// however reflection requires the class to be instantiated.
+		nlassert( false );
+	}
+
+	void CGroupSubMenuBase::hideSubMenus()
+	{
+		// Necessary because it's supposed to be an abstract class,
+		// however reflection requires the class to be instantiated.
+		nlassert( false );
+	}
+
+}
+
diff --git a/code/ryzom/client/src/interface_v3/ctrl_scroll.cpp b/code/ryzom/client/src/interface_v3/ctrl_scroll.cpp
deleted file mode 100644
index 834d3ee5e..000000000
--- a/code/ryzom/client/src/interface_v3/ctrl_scroll.cpp
+++ /dev/null
@@ -1,1058 +0,0 @@
-// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
-// Copyright (C) 2010  Winch Gate Property Limited
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program 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 Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-#include "interface_manager.h"
-#include "nel/gui/widget_manager.h"
-#include "ctrl_scroll.h"
-#include "nel/misc/xml_auto_ptr.h"
-#include "group_menu.h"
-
-#include "nel/gui/lua_ihm.h"
-#include "lua_ihm_ryzom.h"
-
-using namespace NLMISC;
-using namespace std;
-
-NLMISC_REGISTER_OBJECT(CViewBase, CCtrlScroll, std::string, "scroll");
-
-// ------------------------------------------------------------------------------------------------
-CCtrlScroll::CCtrlScroll(const TCtorParam &param)
-:	CCtrlScrollBase(param)
-{
-	_Vertical = true;
-	_Aligned = 1;
-	_TrackPos = 0;
-	_TrackDispPos = 0;
-	_TrackSize = _TrackSizeMin = 16;
-	_Min = 0;
-	_Max = 100;
-	_Value = 0;
-	_InitialValue = 0;
-	_MouseDown = false;
-	_CallingAH = false;
-	_Cancelable = false;
-	_Target = NULL;
-	_Inverted = false;
-	_IsDBLink = false;
-	_LastTargetHReal = 0;
-	_LastTargetMaxHReal = 0;
-	_LastTargetWReal = 0;
-	_LastTargetMaxWReal = 0;
-	_LastTargetOfsX = 0;
-	_LastTargetOfsY = 0;
-	_ObserverOn = true;
-	_TargetStepX = 1;
-	_TargetStepY = 1;
-	_StepValue = 0;
-	_TileM = false;
-	_Frozen = false;
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::runAH(const std::string &name, const std::string &params)
-{
-	if (name.empty()) return;
-	if (_CallingAH) return; // avoid infinite loop
-	_CallingAH = true;
-	CAHManager::getInstance()->runActionHandler(name, this, params);
-	_CallingAH = false;
-}
-
-// ------------------------------------------------------------------------------------------------
-CCtrlScroll::~CCtrlScroll()
-{
-	if (_IsDBLink)
-	{
-		ICDBNode::CTextId textId;
-		_DBLink.getNodePtr()->removeObserver(this, textId);
-	}
-}
-
-// ------------------------------------------------------------------------------------------------
-bool CCtrlScroll::parse(xmlNodePtr node, CInterfaceGroup * parentGroup)
-{
-	if (!CCtrlBase::parse(node, parentGroup))
-		return false;
-
-	CXMLAutoPtr prop;
-	// Read textures
-	prop = (char*) xmlGetProp( node, (xmlChar*)"tx_bottomleft" );
-	if(prop) setTextureBottomOrLeft(string((const char*)prop));
-	else setTextureBottomOrLeft ("w_scroll_l0_b.tga");
-
-	prop = (char*) xmlGetProp( node, (xmlChar*)"tx_middle" );
-	if(prop)	setTextureMiddle(string((const char*)prop));
-	else setTextureMiddle ("w_scroll_l0_m.tga");
-
-	prop = (char*) xmlGetProp( node, (xmlChar*)"tx_topright" );
-	if(prop) setTextureTopOrRight(string((const char*)prop));
-	else setTextureTopOrRight ("w_scroll_l0_t.tga");
-
-	// Read properties
-	prop = (char*) xmlGetProp( node, (xmlChar*)"vertical" );
-	if (prop) _Vertical = convertBool((const char*)prop);
-
-	prop = (char*) xmlGetProp (node, (xmlChar*)"align");
-	_Aligned = 1;
-	if (prop)
-	{
-		if (stricmp(prop, "T") == 0) _Aligned = 0;
-		else if (stricmp(prop, "B") == 0) _Aligned = 1;
-		else if (stricmp(prop, "L") == 0) _Aligned = 2;
-		else if (stricmp(prop, "R") == 0) _Aligned = 3;
-	}
-
-	prop = (char*) xmlGetProp( node, (xmlChar*)"min" );
-	if (prop) fromString((const char*)prop, _Min);
-
-	prop = (char*) xmlGetProp( node, (xmlChar*)"max" );
-	if (prop) fromString((const char*)prop, _Max);
-
-	prop = (char*) xmlGetProp( node, (xmlChar*)"value" );
-	if (prop)
-	{
-		if ( isdigit(*prop) || *prop=='-')
-		{
-			_IsDBLink = false;
-			fromString((const char*)prop, _Value);
-		}
-		else
-		{
-			_IsDBLink = true;
-			_DBLink.link(prop);
-			ICDBNode::CTextId textId;
-			_DBLink.getNodePtr()->addObserver(this, textId);
-
-		}
-	}
-
-	prop = (char*) xmlGetProp( node, (xmlChar*)"tracksize" );
-	if (prop) fromString((const char*)prop, _TrackSize);
-
-	// Read Action handlers
-	prop = (char*) xmlGetProp( node, (xmlChar*)"onscroll" );
-	if (prop)	_AHOnScroll = NLMISC::strlwr(prop);
-	prop = (char*) xmlGetProp( node, (xmlChar*)"params" );
-	if (prop)	_AHOnScrollParams = string((const char*)prop);
-	//
-	prop = (char*) xmlGetProp( node, (xmlChar*)"onscrollend" );
-	if (prop)	_AHOnScrollEnd = NLMISC::strlwr(prop);
-	prop = (char*) xmlGetProp( node, (xmlChar*)"end_params" );
-	if (prop)	_AHOnScrollEndParams = string((const char*)prop);
-	//
-	prop = (char*) xmlGetProp( node, (xmlChar*)"onscrollcancel" );
-	if (prop)	_AHOnScrollCancel = NLMISC::strlwr(prop);
-	prop = (char*) xmlGetProp( node, (xmlChar*)"cancel_params" );
-	if (prop)	_AHOnScrollCancelParams = string((const char*)prop);
-
-
-	// auto-target
-	prop = (char*) xmlGetProp( node, (xmlChar*)"target" );
-	if (prop)
-	{
-		CInterfaceGroup	*group = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(prop));
-		if(group == NULL)
-			group = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(this->getId(), prop));
-
-		if(group != NULL)
-			setTarget (group);
-	}
-
-
-	// auto-step
-	prop = (char*) xmlGetProp( node, (xmlChar*)"target_stepx" );
-	if(prop)	fromString((const char*)prop, _TargetStepX);
-	prop = (char*) xmlGetProp( node, (xmlChar*)"target_stepy" );
-	if(prop)	fromString((const char*)prop, _TargetStepY);
-	_TargetStepX= max((sint32)1, _TargetStepX);
-	_TargetStepY= max((sint32)1, _TargetStepY);
-
-	// Scroll Step
-	prop = (char*) xmlGetProp( node, (xmlChar*)"step_value" );
-	if(prop)	fromString((const char*)prop, _StepValue);
-
-	prop = (char*) xmlGetProp( node, (xmlChar*)"cancelable" );
-	if (prop) _Cancelable = convertBool(prop);
-
-	prop= (char*) xmlGetProp (node, (xmlChar*)"frozen");
-	_Frozen = false;
-	if (prop)
-		_Frozen = convertBool(prop);
-
-
-	return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-
-int CCtrlScroll::luaSetTarget(CLuaState &ls)
-{
-	const char *funcName = "setTarget";
-	CLuaIHM::checkArgCount(ls, funcName, 1);
-	CLuaIHM::checkArgType(ls, funcName, 1, LUA_TSTRING);
-	std::string targetId = ls.toString(1);
-
-	CInterfaceGroup	*group = dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId(targetId));
-	if(group != NULL)
-	{
-		setTarget (group);
-	}
-
-	return 0;
-}
-
-void CCtrlScroll::updateCoords()
-{
-	if (_Target)
-	{
-		// update only if visible
-		if (_Target->getActive())
-		{
-			CViewRenderer &rVR = *CViewRenderer::getInstance();
-			sint32 w, h;
-			rVR.getTextureSizeFromId (_TxIdB, w, h);
-
-			if (_Vertical)
-			{
-				_W = w;
-				_H = _Target->getMaxHReal();
-			}
-			else
-			{
-				_W = _Target->getMaxWReal();
-				_H = h;
-			}
-
-			CCtrlBase::updateCoords ();
-			if (_Vertical)
-			{
-				if(_Target->getHReal()!=_LastTargetHReal || _Target->getMaxHReal()!=_LastTargetMaxHReal ||
-				   _Target->getOfsY() != _LastTargetOfsY
-				  )
-				{
-					_LastTargetHReal= _Target->getHReal();
-					_LastTargetMaxHReal= _Target->getMaxHReal();
-					_LastTargetOfsY = _Target->getOfsY();
-
-					// Activate only if needed
-					setActive(_Target->getHReal() > _Target->getMaxHReal());
-					CCtrlBase::updateCoords();
-
-					// Calculate size of the track button
-					if ((_Target->getHReal() <= _Target->getMaxHReal()) || (_Target->getHReal() == 0))
-					{
-						_TrackSize = _Target->getMaxHReal();
-					}
-					else
-					{
-						float factor = (float)_Target->getMaxHReal() / (float)_Target->getHReal();
-						factor = _TrackSizeMin + factor * (this->getHReal() - _TrackSizeMin);
-						_TrackSize = (sint32)factor;
-					}
-					// Calculate pos of the track button
-					if (_Target->getHReal() <= _Target->getMaxHReal())
-					{
-						if (_Aligned == 1) // BOTTOM
-							_TrackPos = 0;
-						else // TOP
-							_TrackPos = getHReal()-_TrackSize;
-					}
-					else
-					{
-						if (_Aligned == 1) // BOTTOM
-						{
-							float factor = ((float)_Target->getHReal() - (float)_Target->getMaxHReal());
-							factor = -(float)_Target->getOfsY() / factor;
-							if (factor < 0.0f) factor = 0.0f;
-							if (factor > 1.0f) factor = 1.0f;
-							factor = factor * (getHReal()-_TrackSize);
-							_TrackPos = (sint32)factor;
-						}
-						else // TOP
-						{
-							float factor = ((float)_Target->getHReal() - (float)_Target->getMaxHReal());
-							factor = (float)_Target->getOfsY() / factor;
-							if (factor < 0.0f) factor = 0.0f;
-							if (factor > 1.0f) factor = 1.0f;
-							sint32 hreal = getHReal();
-							factor = (1.0f-factor) * (hreal - _TrackSize);
-							_TrackPos = (sint32)factor;
-						}
-					}
-
-					// invalidate coords.
-					computeTargetOfsFromPos();
-				}
-			}
-			else // Horizontal Tracker
-			{
-				if(_Target->getWReal()!=_LastTargetWReal || _Target->getMaxWReal()!=_LastTargetMaxWReal ||
-				   _Target->getOfsX() != _LastTargetOfsX)
-				{
-					_LastTargetWReal= _Target->getWReal();
-					_LastTargetMaxWReal= _Target->getMaxWReal();
-					_LastTargetOfsX = _Target->getOfsX();
-
-					// Activate only if needed
-					setActive(_Target->getWReal() > _Target->getMaxWReal());
-					CCtrlBase::updateCoords();
-
-					// Calculate size of the track button
-					if ((_Target->getWReal() <= _Target->getMaxWReal()) || (_Target->getWReal() == 0))
-					{
-						_TrackSize = _Target->getMaxWReal();
-					}
-					else
-					{
-						float factor = (float)_Target->getMaxWReal() / (float)_Target->getWReal();
-						factor = _TrackSizeMin + factor * (this->getWReal() - _TrackSizeMin);
-						_TrackSize = (sint32)factor;
-					}
-					// Calculate pos of the track button
-					if (_Target->getWReal() <= _Target->getMaxWReal())
-					{
-						if (_Aligned == 2) // LEFT
-							_TrackPos = 0;
-						else // RIGHT
-							_TrackPos = getWReal()-_TrackSize;
-					}
-					else
-					{
-						if (_Aligned == 2) // LEFT
-						{
-							float factor = ((float)_Target->getWReal() - (float)_Target->getMaxWReal());
-							factor = -(float)_Target->getOfsX() / factor;
-							if (factor < 0.0f) factor = 0.0f;
-							if (factor > 1.0f) factor = 1.0f;
-							factor = factor * (getWReal()-_TrackSize);
-							_TrackPos = (sint32)factor;
-						}
-						else // RIGHT
-						{
-							float factor = ((float)_Target->getWReal() - (float)_Target->getMaxWReal());
-							factor = (float)_Target->getOfsX() / factor;
-							if (factor < 0.0f) factor = 0.0f;
-							if (factor > 1.0f) factor = 1.0f;
-							sint32 hreal = getWReal();
-							factor = (1.0f-factor) * (hreal - _TrackSize);
-							_TrackPos = (sint32)factor;
-						}
-					}
-
-					// invalidate coords.
-					computeTargetOfsFromPos();
-				}
-			}
-		}
-		// reset cache
-		else
-		{
-			_LastTargetHReal= 0;
-			_LastTargetMaxHReal= 0;
-			_LastTargetWReal= 0;
-			_LastTargetMaxWReal= 0;
-			_LastTargetOfsX = 0;
-			_LastTargetOfsY = 0;
-			setActive(false);
-		}
-	}
-	else
-	{
-		CCtrlBase::updateCoords ();
-		if (_IsDBLink)
-			_Value = _DBLink.getSInt32();
-		if (_Vertical)
-		{
-			float factor;
-			if (_Aligned == 1) // BOTTOM
-				factor = ((float)_Value-_Min) / (_Max-_Min);
-			else // TOP
-				factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
-			factor *= (this->getHReal() - _TrackSize);
-
-			_TrackDispPos = (sint32)factor;
-		}
-		else
-		{
-			float factor;
-			if (_Aligned == 2) // LEFT
-				factor = ((float)_Value-_Min) / (_Max-_Min);
-			else // RIGHT
-				factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
-			factor *= (this->getWReal() - _TrackSize);
-
-			_TrackDispPos = (sint32)factor;
-		}
-	}
-	CCtrlBase::updateCoords ();
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::draw()
-{
-	CViewRenderer &rVR = *CViewRenderer::getInstance();
-	CRGBA col = CWidgetManager::getInstance()->getGlobalColorForContent();
-
-	if (_Target)
-	{
-		if (_Vertical)
-		{
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackPos, _WReal, 4, 0, false, _TxIdB, col );
-			if (_TileM == 0)
-				rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, col );
-			else
-				rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal, _YReal+_TrackPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, _TileM-1, col );
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackPos+_TrackSize-4, _WReal, 4, 0, false, _TxIdT, col );
-		}
-		else
-		{
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackPos, _YReal, 4, _HReal, 0, false, _TxIdB, col );
-			if (_TileM == 0)
-				rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, col );
-			else
-				rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal+_TrackPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, _TileM-1, col );
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackPos+_TrackSize-4, _YReal, 4, _HReal, 0, false, _TxIdT, col );
-		}
-	}
-	else
-	{
-		if (_Vertical)
-		{
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackDispPos, _WReal, 4, 0, false, _TxIdB, col );
-			if (_TileM == 0)
-				rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackDispPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, col );
-			else
-				rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal, _YReal+_TrackDispPos+4, _WReal, _TrackSize-8, 0, false, _TxIdM, _TileM-1, col );
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_TrackDispPos+_TrackSize-4, _WReal, 4, 0, false, _TxIdT, col );
-		}
-		else
-		{
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackDispPos, _YReal, 4, _HReal, 0, false, _TxIdB, col );
-			if (_TileM == 0)
-				rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackDispPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, col );
-			else
-				rVR.drawRotFlipBitmapTiled (_RenderLayer, _XReal+_TrackDispPos+4, _YReal, _TrackSize-8, _HReal, 0, false, _TxIdM, _TileM-1, col );
-			rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_TrackDispPos+_TrackSize-4, _YReal, 4, _HReal, 0, false, _TxIdT, col );
-		}
-	}
-}
-
-// ------------------------------------------------------------------------------------------------
-bool CCtrlScroll::handleEvent (const NLGUI::CEventDescriptor &event)
-{
-	if (CCtrlBase::handleEvent(event)) return true;
-	if (!_Active || _Frozen)
-		return false;
-	if (event.getType() == NLGUI::CEventDescriptor::mouse)
-	{
-		const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
-		if ((CWidgetManager::getInstance()->getCapturePointerLeft() != this) &&
-			(!((eventDesc.getX() >= _XReal) &&
-			(eventDesc.getX() < (_XReal + _WReal))&&
-			(eventDesc.getY() > _YReal) &&
-			(eventDesc.getY() <= (_YReal+ _HReal)))))
-			return false;
-
-		if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown)
-		{
-			_MouseDown = true;
-			_InitialValue = getValue();
-			if (!_Target)
-				_TrackPos = _TrackDispPos;
-			_MouseDownOffsetX = eventDesc.getX() - (getXReal() + (_Vertical ? 0 : _TrackPos));
-			_MouseDownOffsetY = eventDesc.getY() - (getYReal() + (_Vertical ? _TrackPos : 0));
-
-			// if target is a menu, hidde its sub menus
-			if(_Target && _Target->getParent())
-			{
-				CGroupSubMenu * menu = dynamic_cast<CGroupSubMenu*>(_Target->getParent());
-				if(menu)
-					menu->hideSubMenus();
-			}
-			return true;
-		}
-		if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup)
-		{
-			_MouseDown = false;
-			runAH(_AHOnScrollEnd, _AHOnScrollEndParams.empty() ? _AHOnScrollParams : _AHOnScrollEndParams); // backward compatibility
-			return true;
-		}
-		if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown && _MouseDown && _Cancelable)
-		{
-			_MouseDown = false;
-			setValue(_InitialValue);
-			runAH(_AHOnScrollCancel, _AHOnScrollCancelParams); // backward compatibility
-			return true;
-		}
-		if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousemove)
-		{
-			if (_MouseDown)
-			{
-				sint32 dx = eventDesc.getX() - (getXReal() + (_Vertical ? 0 : _TrackPos) + _MouseDownOffsetX);
-				sint32 dy = eventDesc.getY() - (getYReal() + (_Vertical ? _TrackPos : 0 ) + _MouseDownOffsetY);
-				if (dx != 0) moveTrackX (dx);
-				if (dy != 0) moveTrackY (dy);
-			}
-			return true;
-		}
-		if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel && _Vertical)
-		{
-			moveTrackY (eventDesc.getWheel() * 12);
-			return true;
-		}
-	}
-	return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::setTarget (CInterfaceGroup *pIG)
-{
-	_Target = pIG;
-
-	if (_Vertical)
-	{
-		if (_Target->getPosRef()&Hotspot_Tx)
-			_Aligned = 0;
-		else
-			_Aligned = 1;
-
-		if (_Target->getPosRef()&Hotspot_Tx)
-			_Inverted = true;
-		else
-			_Inverted = true;
-	}
-	else
-	{
-		if (_Target->getPosRef()&Hotspot_xL)
-			_Aligned = 2;
-		else
-			_Aligned = 3;
-
-		if (_Target->getPosRef()&Hotspot_xL)
-			_Inverted = true;
-		else
-			_Inverted = true;
-	}
-}
-// ------------------------------------------------------------------------------------------------
-sint32 CCtrlScroll::moveTrackX (sint32 dx)
-{
-	if (_Vertical)
-		return 0;
-	if ((getWReal()-_TrackSize) <= 0)
-		return 0;
-
-	sint32 newtpos;
-	sint32 tpos = _TrackPos;
-	sint32 tsize = _TrackSize;
-
-	// Limit the scroller to the defined area
-	newtpos = tpos + dx;
-	if (newtpos < 0) newtpos = 0;
-	if (newtpos > (getWReal()-tsize)) newtpos = (getWReal()-tsize);
-	dx = newtpos - tpos;
-
-	if (_Target)
-	{
-		_TrackPos = newtpos;
-
-		computeTargetOfsFromPos();
-	}
-	else // This is a number scroller
-	{
-		float factor = (float)(_Max - _Min);
-
-		if (_Aligned == 2) // LEFT
-			factor = -factor * newtpos / (float)(getWReal()-tsize) - _Min;
-		else // RIGHT
-			factor = factor * (1.0f-(newtpos / (float)(getWReal()-tsize))) + _Min;
-
-		_TrackPos = newtpos;
-
-		if (_Aligned == 2) // LEFT
-			_Value = (sint32) (_Inverted ? factor : -factor);
-		else // RIGHT
-			_Value = (sint32) (_Inverted ? factor : -factor);
-
-		// step and clamp value
-		normalizeValue(_Value);
-
-		{
-			float factor;
-			if (_Aligned == 2) // LEFT
-				factor = ((float)_Value-_Min) / (_Max-_Min);
-			else // RIGHT
-				factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
-			factor *= (this->getWReal() - _TrackSize);
-
-			_TrackDispPos = (sint32)factor;
-		}
-
-		if (_IsDBLink)
-		{
-			_ObserverOn = false;
-			_DBLink.setSInt32 (_Value);
-			_ObserverOn = true;
-		}
-	}
-
-	// Launch the scroller event if any
-	runAH(_AHOnScroll, _AHOnScrollParams);
-
-	return dx;
-}
-
-// ------------------------------------------------------------------------------------------------
-sint32 CCtrlScroll::moveTrackY (sint32 dy)
-{
-	if (!_Vertical)
-		return 0;
-	if ((getHReal()-_TrackSize) <= 0)
-		return 0;
-
-	sint32 newtpos;
-	sint32 tpos = _TrackPos;
-	sint32 tsize = _TrackSize;
-
-	// Limit the scroller to the defined area
-	newtpos = tpos + dy;
-	if (newtpos < 0) newtpos = 0;
-	if (newtpos > (getHReal()-tsize)) newtpos = (getHReal()-tsize);
-	dy = newtpos - tpos;
-
-	if (_Target)
-	{
-		_TrackPos = newtpos;
-
-		computeTargetOfsFromPos();
-	}
-	else // This is a number scroller
-	{
-		float factor = (float)(_Max - _Min);
-
-		if (_Aligned == 1) // BOTTOM
-			factor = -factor * newtpos / (float)(getHReal()-tsize) - _Min;
-		else // TOP
-			factor = factor * (1.0f-(newtpos / (float)(getHReal()-tsize))) + _Min;
-
-		_TrackPos = newtpos;
-
-		if (_Aligned == 1) // BOTTOM
-			_Value = (sint32) (_Inverted ? factor : -factor);
-		else // TOP
-			_Value = (sint32) (_Inverted ? factor : -factor);
-
-		// step and clamp value
-		normalizeValue(_Value);
-
-		{
-			float factor;
-			if (_Aligned == 1) // BOTTOM
-				factor = ((float)_Value-_Min) / (_Max-_Min);
-			else // TOP
-				factor = 1.0f - ((float)_Value-_Min) / (_Max-_Min);
-			factor *= (this->getHReal() - _TrackSize);
-
-			_TrackDispPos = (sint32)factor;
-		}
-
-		if (_IsDBLink)
-		{
-			_ObserverOn = false;
-			_DBLink.setSInt32 (_Value);
-			_ObserverOn = true;
-		}
-	}
-
-	// Launch the scroller event if any
-	runAH(_AHOnScroll, _AHOnScrollParams);
-
-	return dy;
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::setTextureBottomOrLeft (const std::string &txName)
-{
-	CViewRenderer &rVR = *CViewRenderer::getInstance();
-	_TxIdB = rVR.getTextureIdFromName(txName);
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::setTextureMiddle (const std::string &txName)
-{
-	CViewRenderer &rVR = *CViewRenderer::getInstance();
-	_TxIdM = rVR.getTextureIdFromName(txName);
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::setTextureTopOrRight (const std::string &txName)
-{
-	CViewRenderer &rVR = *CViewRenderer::getInstance();
-	_TxIdT = rVR.getTextureIdFromName(txName);
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::setValue(sint32 value)
-{
-	normalizeValue(value);
-
-	if (_IsDBLink)
-	{
-		_ObserverOn = false;
-		_DBLink.setSInt32(value);
-		_ObserverOn = true;
-	}
-	else
-	{
-		_Value = value;
-	}
-	invalidateCoords();
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::setTrackPos(sint32 pos)
-{
-	if (_Vertical)
-	{
-		moveTrackY(pos - _TrackPos);
-	}
-	else
-	{
-		moveTrackX(pos - _TrackPos);
-	}
-	invalidateCoords();
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::computeTargetOfsFromPos()
-{
-	if(_Vertical)
-	{
-		float factor = ((float)_Target->getHReal() - (float)_Target->getMaxHReal());
-
-		if (_Aligned == 1) // BOTTOM
-			factor = -factor * _TrackPos / favoid0((float)(getHReal()-_TrackSize));
-		else // TOP
-			factor = factor * (1.0f-(_TrackPos / favoid0((float)(getHReal()-_TrackSize))));
-
-		// Compute Steped target
-		sint32	nexOfsY= (sint32) (_Inverted ? factor : -factor);
-		if(_TargetStepY>1)
-			nexOfsY= ((nexOfsY+_TargetStepY/2)/_TargetStepY) * _TargetStepY;
-		_Target->setOfsY (nexOfsY);
-		_LastTargetOfsY = nexOfsY;
-
-		// invalidate only XReal/YReal, doing only 1 pass
-		_Target->invalidateCoords(1);
-	}
-	else
-	{
-		float factor = ((float)_Target->getWReal() - (float)_Target->getMaxWReal());
-
-		if (_Aligned == 2) // LEFT
-			factor = -factor * _TrackPos / favoid0((float)(getWReal()-_TrackSize));
-		else // RIGHT
-			factor = factor * (1.0f-(_TrackPos / favoid0((float)(getWReal()-_TrackSize))));
-
-		// Compute Steped target
-		sint32	nexOfsX= (sint32) (_Inverted ? factor : -factor);
-		if(_TargetStepX>1)
-			nexOfsX= ((nexOfsX+_TargetStepX/2)/_TargetStepX) * _TargetStepX;
-		_Target->setOfsX (nexOfsX);
-		_LastTargetOfsX = nexOfsX;
-
-		// invalidate only XReal/YReal, doing only 1 pass
-		_Target->invalidateCoords(1);
-	}
-}
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::update(ICDBNode * /* node */)
-{
-	if (!_ObserverOn) return;
-	_Value = _DBLink.getSInt32();
-	// the value in the db changed
-	invalidateCoords(1);
-	if (_Target) _Target->invalidateCoords(1);
-}
-
-
-// ***************************************************************************
-void	CCtrlScroll::moveTargetX (sint32 dx)
-{
-	if(!_Target)
-		return;
-	sint32	maxWReal= _Target->getMaxWReal();
-	sint32	wReal= _Target->getWReal();
-	if(wReal <= maxWReal)
-		return;
-
-	// compute the new ofsX.
-	sint32	ofsX= _Target->getOfsX();
-	ofsX+= dx;
-	clamp(ofsX, 0, wReal-maxWReal);
-	_Target->setOfsX(ofsX);
-
-	// compute new trackPos.
-	if (_Aligned == 2) // LEFT
-	{
-		float factor = (float)(wReal-maxWReal);
-		factor = -(float)ofsX / factor;
-		clamp(factor, 0.f, 1.f);
-		factor = factor * (getWReal()-_TrackSize);
-		_TrackPos = (sint32)factor;
-	}
-	else // RIGHT
-	{
-		float factor = (float)(wReal-maxWReal);
-		factor = (float)ofsX / factor;
-		clamp(factor, 0.f, 1.f);
-		factor = (1.0f-factor) * (getWReal() - _TrackSize);
-		_TrackPos = (sint32)factor;
-	}
-
-	// invalidate only position. 1 pass is sufficient
-	invalidateCoords(1);
-}
-
-// ***************************************************************************
-void	CCtrlScroll::moveTargetY (sint32 dy)
-{
-	if(!_Target)
-		return;
-	sint32	maxHReal= _Target->getMaxHReal();
-	sint32	hReal= _Target->getHReal();
-	if(hReal <= maxHReal)
-		return;
-
-	// compute the new ofsY.
-	sint32	ofsY= _Target->getOfsY();
-	ofsY+= dy;
-
-	// compute new trackPos.
-	if (_Aligned == 1) // BOTTOM
-	{
-		clamp(ofsY, maxHReal - hReal, 0);
-		_Target->setOfsY(ofsY);
-		float factor = (float)(hReal-maxHReal);
-		factor = -(float)ofsY / factor;
-		clamp(factor, 0.f, 1.f);
-		factor = factor * (getHReal()-_TrackSize);
-		_TrackPos = (sint32)factor;
-	}
-	else // TOP
-	{
-		clamp(ofsY, 0, hReal-maxHReal);
-		_Target->setOfsY(ofsY);
-		float factor = (float)(hReal-maxHReal);
-		factor = (float)ofsY / factor;
-		clamp(factor, 0.f, 1.f);
-		factor = (1.0f-factor) * (getHReal() - _TrackSize);
-		_TrackPos = (sint32)factor;
-	}
-
-	// invalidate only position. 1 pass is sufficient
-	invalidateCoords(1);
-}
-
-// ***************************************************************************
-void	CCtrlScroll::normalizeValue(sint32 &value)
-{
-	// if, 0 no step
-	if(_StepValue==0 || _StepValue==1)
-		return;
-	// if interval is null, force min!
-	if(_Max==_Min)
-	{
-		value= _Min;
-		return;
-	}
-
-	// get range of possible position
-//	sint32	size= _Max - _Min;
-
-	// step (round)
-	sint32	val= (value + (_StepValue/2) -_Min) / _StepValue;
-	val= _Min + val * _StepValue;
-	clamp(val, _Min, _Max);
-	value= val;
-}
-
-// ***************************************************************************
-void CCtrlScroll::setFrozen (bool state)
-{
-	_Frozen = state;
-	if (_Frozen)
-	{
-		_Value = 0;
-	}
-}
-
-
-// ------------------------------------------------------------------------------------------------
-int CCtrlScroll::luaEnsureVisible(CLuaState &ls)
-{
-	const char *funcName = "ensureVisible";
-	CLuaIHM::checkArgCount(ls, funcName, 3);
-	CLuaIHM::checkArgTypeUIElement(ls, funcName, 1);
-	CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING);
-	CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING);
-	THotSpot	hs[2];
-	std::string hsStr[] = { ls.toString(2), ls.toString(3) };
-	//
-	for (uint hsIndex = 0; hsIndex < 2; ++ hsIndex)
-	{
-		if (_Vertical)
-		{
-			if (NLMISC::nlstricmp(hsStr[hsIndex], "T") == 0)
-			{
-				hs[hsIndex] = Hotspot_Tx;
-			}
-			else
-			if (NLMISC::nlstricmp(hsStr[hsIndex], "M") == 0)
-			{
-				hs[hsIndex] = Hotspot_Mx;
-			}
-			else
-			if (NLMISC::nlstricmp(hsStr[hsIndex], "B") == 0)
-			{
-				hs[hsIndex] = Hotspot_Bx;
-			}
-			else
-			{
-				CLuaIHM::fails(ls, "%s : couldn't parse hotspot for vertical scrollbar", funcName);
-			}
-		}
-		else
-		{
-			if (NLMISC::nlstricmp(hsStr[hsIndex], "L") == 0)
-			{
-				hs[hsIndex] = Hotspot_xL;
-			}
-			else
-			if (NLMISC::nlstricmp(hsStr[hsIndex], "M") == 0)
-			{
-				hs[hsIndex] = Hotspot_xM;
-			}
-			else
-			if (NLMISC::nlstricmp(hsStr[hsIndex], "R") == 0)
-			{
-				hs[hsIndex] = Hotspot_xR;
-			}
-			else
-			{
-				CLuaIHM::fails(ls, "%s : couldn't parse hotspot for horizontal scrollbar", funcName);
-			}
-		}
-	}
-	ensureVisible(CLuaIHM::getUIOnStack(ls, 1), hs[0], hs[1]);
-	return 0;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-void CCtrlScroll::ensureVisible(CInterfaceElement *childElement, THotSpot childHotSpot, THotSpot parentHotSpot)
-{
-	if (!_Target) return; // not connected to a target yet
-	if (!childElement) return;
-	// compute corners of interest for enclosed element & enclosing group
-	sint32 childX, childY;
-	childElement->getCorner(childX, childY, childHotSpot);
-	if (_Vertical)
-	{
-		sint32	maxHReal= _Target->getMaxHReal();
-		sint32	hReal=	  _Target->getHReal();
-		if(hReal > maxHReal)
-		{
-			sint enclosingDY;
-			switch (parentHotSpot)
-			{
-				case Hotspot_Bx:
-					enclosingDY = maxHReal;
-				break;
-				case Hotspot_Mx:
-					enclosingDY = maxHReal / 2;
-				break;
-				case Hotspot_Tx:
-					enclosingDY = 0;
-				break;
-				default:
-					nlassert(0);
-				break;
-			}
-			if (_Aligned == 0)
-			{
-				// Top aligned case
-				sint32 offsetY = (_Target->getYReal() + _Target->getHReal() - childY) - enclosingDY;
-				NLMISC::clamp(offsetY, 0, hReal - maxHReal);
-				_Target->setOfsY(offsetY);
-				_Target->invalidateCoords();
-			}
-			else if (_Aligned == 1)
-			{
-				// Bottom aligned case
-				sint32 offsetY = (maxHReal - enclosingDY) - (childY - _Target->getYReal());
-				NLMISC::clamp(offsetY, maxHReal - hReal, 0);
-				_Target->setOfsY(offsetY);
-				_Target->invalidateCoords();
-			}
-		}
-		// else, ... fully visible (not occluded by parent group)
-	}
-	else
-	{
-		sint32	maxWReal= _Target->getMaxWReal();
-		sint32	wReal=	  _Target->getWReal();
-		if(wReal > maxWReal)
-		{
-			sint enclosingDX;
-			switch (parentHotSpot)
-			{
-				case Hotspot_xL:
-					enclosingDX = maxWReal;
-				break;
-				case Hotspot_xM:
-					enclosingDX = maxWReal / 2;
-				break;
-				case Hotspot_xR:
-					enclosingDX = 0;
-				break;
-				default:
-					nlassert(0);
-				break;
-			}
-			if (_Aligned == 3)
-			{
-				// right aligned case
-				sint32 offsetX = (_Target->getXReal() + _Target->getWReal() - childX) - enclosingDX;
-				NLMISC::clamp(offsetX, 0, wReal - maxWReal);
-				_Target->setOfsX(offsetX);
-				_Target->invalidateCoords();
-			}
-			else if (_Aligned == 2)
-			{
-				// Left aligned case
-				sint32 offsetX = (maxWReal - enclosingDX) - (childX - _Target->getXReal());
-				NLMISC::clamp(offsetX, maxWReal - wReal, 0);
-				_Target->setOfsX(offsetX);
-				_Target->invalidateCoords();
-			}
-		}
-		// else, ... fully visible (not occluded by parent group)
-	}
-}
-
diff --git a/code/ryzom/client/src/interface_v3/ctrl_scroll.h b/code/ryzom/client/src/interface_v3/ctrl_scroll.h
deleted file mode 100644
index d1e6fe2d3..000000000
--- a/code/ryzom/client/src/interface_v3/ctrl_scroll.h
+++ /dev/null
@@ -1,196 +0,0 @@
-// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
-// Copyright (C) 2010  Winch Gate Property Limited
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program 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 Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-
-#ifndef RZ_CTRL_SCROLL_H
-#define RZ_CTRL_SCROLL_H
-
-#include "nel/misc/types_nl.h"
-#include "nel/gui/ctrl_scroll_base.h"
-
-/**
- * Class handling scollbar function
- * \author Matthieu 'TrapII' Besson
- * \author Nevrax France
- * \date 2002
- */
-class CCtrlScroll : public CCtrlScrollBase, public NLMISC::ICDBNode::IPropertyObserver
-{
-
-public:
-	DECLARE_UI_CLASS( CCtrlScroll )
-	CCtrlScroll(const TCtorParam &param);
-	~CCtrlScroll();
-
-
-	virtual bool parse(xmlNodePtr cur, CInterfaceGroup * parentGroup);
-
-	virtual void updateCoords();
-	virtual void draw();
-	virtual bool handleEvent (const NLGUI::CEventDescriptor &event);
-
-	void	setTarget (CInterfaceGroup *pIG);
-	// Return the delta value the track has moved
-	sint32	moveTrackX (sint32 dx);
-	sint32	moveTrackY (sint32 dy);
-
-	/** Move the Target Ofs with a Delta, and recompute TrackPos from this Ofs.
-	 *	Useful for finer controled group scrolling when the list is very big (with mouseWheel or scroll buttons)
-	 */
-	void	moveTargetX (sint32 dx);
-	void	moveTargetY (sint32 dy);
-
-	void	setAlign (sint32 nAlign) { _Aligned = nAlign; }
-	// invert the factor for target
-	void	setInverted(bool invert) { _Inverted = invert; }
-
-	void	setTextureBottomOrLeft	(const std::string &txName);
-	void	setTextureMiddle		(const std::string &txName);
-	void	setTextureTopOrRight	(const std::string &txName);
-
-	void	setTextureBottomOrLeft	(sint32 txid) { _TxIdB = txid; }
-	void	setTextureMiddle		(sint32 txid) { _TxIdM = txid; }
-	void	setTextureMiddleTile	(uint8 tile) { _TileM = tile; } // 0 - not tiled (1 BL) (2 BR) (3 TL) (4 TR)
-	void	setTextureTopOrRight	(sint32 txid) { _TxIdT = txid; }
-
-	// number scroller
-	sint32	getValue() const { return _IsDBLink ? _DBLink.getSInt32() : _Value; }
-	// NB: the value is clamped (see setMinMax) and stepped (see setStepValue())
-	void	setValue(sint32 value);
-	void	setMinMax(sint32 nMin, sint32 nMax) { _Min = nMin; _Max = nMax; }
-	void	setStepValue(uint32 step) { _StepValue= step; }
-
-	void	setTrackPos(sint32 pos);
-	sint32	getTrackPos() const { return _TrackPos; }
-	sint32	getTrackSize() const { return _TrackSize; }
-	// dummy set for track size (forlua export)
-	void	setTrackSize(sint32 /* trackSize */) { throw  NLMISC::Exception("TrackSize is read-only"); }
-
-
-	void	setFrozen (bool state);
-	bool	getFrozen () const { return _Frozen; }
-
-	int luaSetTarget(CLuaState &ls);
-	int luaEnsureVisible(CLuaState &ls);
-
-	// name
-	void			setName(const std::string & val) {_Name = val;}
-	std::string		getName() const {return _Name;}
-
-	// max
-	void			setMax(sint32 max) {_Max = max;}
-	sint32			getMax() const {return _Max;}
-
-	REFLECT_EXPORT_START(CCtrlScroll, CCtrlScrollBase)
-		REFLECT_LUA_METHOD("setTarget", luaSetTarget)
-		REFLECT_LUA_METHOD("ensureVisible", luaEnsureVisible);
-		REFLECT_SINT32("value", getValue, setValue);
-		REFLECT_SINT32("trackPos", getTrackPos, setTrackPos);
-		REFLECT_SINT32("trackSize", getTrackSize, setTrackSize);
-		REFLECT_STRING("name", getName, setName);
-		REFLECT_SINT32("max", getMax, setMax);
-	REFLECT_EXPORT_END
-
-	/** Ensure that a child element be visible into the frame through which
-	  * its parent group is displayed.
-	  * Example : Had we a list of items for which we want some item 'itemPtr' to have its top position
-	  * matching the middle of the list, we would do :
-	  * this->ensureVisible(itemPtr, Hotspot_Tx, Hotspot_Mx);
-	  *
-	  * The scrollbar will be moved accordingly.
-	  */
-	void ensureVisible(CInterfaceElement *childElement, THotSpot childHotSpot, THotSpot parentHotSpot);
-
-
-protected:
-
-	CInterfaceProperty	_DBLink;	// If this is a value scroller we can link it with db
-	sint32				_Value;		// Or we can use a normal value
-	sint32				_InitialValue;
-
-	sint32 _Min, _Max;
-	std::string _AHOnScroll;
-	std::string _AHOnScrollParams;
-	//
-	std::string _AHOnScrollEnd;
-	std::string _AHOnScrollEndParams;
-	//
-	//
-	std::string _AHOnScrollCancel;
-	std::string _AHOnScrollCancelParams;
-
-
-	sint32 _Aligned; // 0-Top 1-Bottom 2-Left 3-Right
-
-	sint32 _TrackDispPos;
-	sint32 _TrackPos;
-	sint32 _TrackSize;
-	sint32 _TrackSizeMin;
-
-	sint32 _MouseDownOffsetX;
-	sint32 _MouseDownOffsetY;
-
-	sint32 _TxIdB; // Same as Left if Horizontal sb
-	sint32 _TxIdM;
-	sint32 _TxIdT; // Same as Right if Horizontal sb
-
-	uint8	_TileM;
-
-	sint32 _LastTargetHReal;
-	sint32 _LastTargetMaxHReal;
-	sint32 _LastTargetOfsY;
-	sint32 _LastTargetWReal;
-	sint32 _LastTargetMaxWReal;
-	sint32 _LastTargetOfsX;
-
-	bool	_Vertical   : 1; // true if vertical track bar
-	bool	_IsDBLink   : 1;
-	bool	_ObserverOn : 1;
-	bool    _Inverted   : 1;
-	bool    _MouseDown  : 1;
-	bool	_CallingAH  : 1;
-	bool	_Cancelable : 1; // true if the slider may be cancelled when pressed on the mouse right button
-	bool	_Frozen		: 1;
-
-	// For Target Scroller only: the target offset step in pixel.
-	sint32	_TargetStepX;
-	sint32	_TargetStepY;
-
-	// For Value Scroller only: indicate the step the scroll bar has. 0 or 1 means no step
-	uint32	_StepValue;
-
-	// Slider's name
-	std::string _Name;
-
-	void	computeTargetOfsFromPos();
-
-	// from IPropertyObserver
-	virtual void update(NLMISC::ICDBNode *node);
-
-	// step the value, and clamp it
-	void	normalizeValue(sint32 &value);
-
-	void runAH(const std::string &name, const std::string &params);
-
-};
-
-
-#endif // RZ_CTRL_SCROLL_H
-
-/* End of ctrl_scroll.h */
-
-
diff --git a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet.h b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet.h
index 894a34ea8..f9b29d83e 100644
--- a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet.h
+++ b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet.h
@@ -26,10 +26,10 @@
 namespace NLGUI
 {
 	class CCtrlBaseButton;
+	class CCtrlScroll;
 }
 
 // ***************************************************************************
-class	CCtrlScroll;
 class CGroupContainer;
 
 // ***************************************************************************
diff --git a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h
index f27dd02e7..f11faabbf 100644
--- a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h
+++ b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_text.h
@@ -30,11 +30,11 @@
 namespace NLGUI
 {
 	class CCtrlButton;
+	class CCtrlScroll;
 }
 
 
 // ***************************************************************************
-class	CCtrlScroll;
 class	CHandlerListSheetTradeSelect;
 class	CHandlerListSheetTradeRightClick;
 class CGroupContainer;
diff --git a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.h b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.h
index 23c96c0c3..30957ae43 100644
--- a/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.h
+++ b/code/ryzom/client/src/interface_v3/dbgroup_list_sheet_trade.h
@@ -25,12 +25,12 @@
 
 namespace NLGUI
 {
-	class	CCtrlButton;
+	class CCtrlButton;
+	class CCtrlScroll;
 }
 
 
 // ***************************************************************************
-class	CCtrlScroll;
 class	CHandlerListSheetTradeSelect;
 class	CHandlerListSheetTradeRightClick;
 
diff --git a/code/ryzom/client/src/interface_v3/group_container.cpp b/code/ryzom/client/src/interface_v3/group_container.cpp
index dcc8b2a4d..e4b80a016 100644
--- a/code/ryzom/client/src/interface_v3/group_container.cpp
+++ b/code/ryzom/client/src/interface_v3/group_container.cpp
@@ -33,7 +33,7 @@
 
 #include "group_list.h"
 #include "nel/gui/ctrl_button.h"
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 #include "view_text.h"
 #include "view_bitmap.h"
 #include "../time_client.h"
diff --git a/code/ryzom/client/src/interface_v3/group_container.h b/code/ryzom/client/src/interface_v3/group_container.h
index bd23a8b38..0a79f0931 100644
--- a/code/ryzom/client/src/interface_v3/group_container.h
+++ b/code/ryzom/client/src/interface_v3/group_container.h
@@ -27,10 +27,10 @@ namespace NLGUI
 {
 	class CEventDescriptorLocalised;
 	class CCtrlButton;
+	class CCtrlScroll;
 }
 
 class CInterfaceList;
-class CCtrlScroll;
 class CViewText;
 class COptionsContainerInsertion;
 class COptionsContainerMove;
diff --git a/code/ryzom/client/src/interface_v3/group_html.cpp b/code/ryzom/client/src/interface_v3/group_html.cpp
index 254a2a2c9..51b65d236 100644
--- a/code/ryzom/client/src/interface_v3/group_html.cpp
+++ b/code/ryzom/client/src/interface_v3/group_html.cpp
@@ -32,7 +32,7 @@ extern "C"
 #include "group_list.h"
 #include "group_container.h"
 #include "view_link.h"
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 #include "nel/gui/ctrl_button.h"
 #include "dbctrl_sheet.h"
 #include "ctrl_text_button.h"
diff --git a/code/ryzom/client/src/interface_v3/group_html.h b/code/ryzom/client/src/interface_v3/group_html.h
index 333137651..beca17afd 100644
--- a/code/ryzom/client/src/interface_v3/group_html.h
+++ b/code/ryzom/client/src/interface_v3/group_html.h
@@ -40,10 +40,10 @@ extern "C"
 namespace NLGUI
 {
 	class CCtrlButton;
+	class CCtrlScroll;
 }
 
 class CGroupList;
-class CCtrlScroll;
 class CDBGroupComboBox;
 class CGroupParagraph;
 
diff --git a/code/ryzom/client/src/interface_v3/group_menu.cpp b/code/ryzom/client/src/interface_v3/group_menu.cpp
index bd2f44088..da2681f53 100644
--- a/code/ryzom/client/src/interface_v3/group_menu.cpp
+++ b/code/ryzom/client/src/interface_v3/group_menu.cpp
@@ -112,7 +112,7 @@ void CViewTextMenu::setAlpha (sint32 a)
 
 // ------------------------------------------------------------------------------------------------
 CGroupSubMenu::CGroupSubMenu(const TCtorParam &param)
-: CGroupFrame(param)
+: CGroupSubMenuBase(param)
 {
 	_SelectionView = NULL;
 	_GroupList = NULL;
diff --git a/code/ryzom/client/src/interface_v3/group_menu.h b/code/ryzom/client/src/interface_v3/group_menu.h
index 8f3098996..41bcae76a 100644
--- a/code/ryzom/client/src/interface_v3/group_menu.h
+++ b/code/ryzom/client/src/interface_v3/group_menu.h
@@ -21,14 +21,18 @@
 
 #include "nel/gui/interface_group.h"
 #include "nel/gui/group_modal.h"
+#include "nel/gui/group_submenu_base.h"
 #include "view_text.h"
-
 #include "ctrl_text_button.h"
 
+namespace NLGUI
+{
+	class CCtrlScroll;
+}
+
 class CViewBitmap;
 class CGroupMenu;
 class CGroupList;
-class CCtrlScroll;
 
 
 /**
@@ -92,7 +96,7 @@ private:
  * \date 2002
  */
 
-class CGroupSubMenu : public CGroupFrame
+class CGroupSubMenu : public CGroupSubMenuBase
 {
 public:
 
@@ -198,7 +202,7 @@ public:
 	int luaReset(CLuaState &ls);
 	int luaSetMaxVisibleLine(CLuaState &ls);
 	//
-	REFLECT_EXPORT_START(CGroupSubMenu, CGroupFrame)
+	REFLECT_EXPORT_START(CGroupSubMenu, CGroupSubMenuBase)
 		REFLECT_LUA_METHOD("getNumLine", luaGetNumLine);
 		REFLECT_LUA_METHOD("getLineId", luaGetLineId); // return the id of a line from its index
 		REFLECT_LUA_METHOD("getLineFromId", luaGetLineFromId); // return -1 if line with id is not found
diff --git a/code/ryzom/client/src/interface_v3/group_scrolltext.cpp b/code/ryzom/client/src/interface_v3/group_scrolltext.cpp
index 411b3714f..89e556870 100644
--- a/code/ryzom/client/src/interface_v3/group_scrolltext.cpp
+++ b/code/ryzom/client/src/interface_v3/group_scrolltext.cpp
@@ -23,7 +23,7 @@
 #include "group_scrolltext.h"
 #include "group_list.h"
 #include "view_text.h"
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 #include "nel/gui/ctrl_button.h"
 #include "nel/gui/action_handler.h"
 
diff --git a/code/ryzom/client/src/interface_v3/group_scrolltext.h b/code/ryzom/client/src/interface_v3/group_scrolltext.h
index e0b11b91d..cfedb76bc 100644
--- a/code/ryzom/client/src/interface_v3/group_scrolltext.h
+++ b/code/ryzom/client/src/interface_v3/group_scrolltext.h
@@ -26,10 +26,10 @@
 namespace NLGUI
 {
 	class CCtrlBaseButton;
+	class CCtrlScroll;
 }
 
 class CGroupList;
-class CCtrlScroll;
 
 // Can be used to build a chat window or anything that displays sequences of strings
 /**
diff --git a/code/ryzom/client/src/interface_v3/interface_config.cpp b/code/ryzom/client/src/interface_v3/interface_config.cpp
index 34fb9d52e..de9924061 100644
--- a/code/ryzom/client/src/interface_v3/interface_config.cpp
+++ b/code/ryzom/client/src/interface_v3/interface_config.cpp
@@ -21,7 +21,7 @@
 #include "interface_config.h"
 #include "interface_manager.h"
 #include "group_container.h"
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 
 using namespace NLMISC;
 using namespace std;
diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp
index 53af9d8e4..89c1bc64b 100644
--- a/code/ryzom/client/src/interface_v3/interface_manager.cpp
+++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp
@@ -51,7 +51,7 @@
 #include "view_bitmap_combo.h"
 #include "view_text.h"
 // Ctrl
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 #include "nel/gui/ctrl_button.h"
 #include "ctrl_text_button.h"
 // DBCtrl
diff --git a/code/ryzom/client/src/interface_v3/interface_manager.h b/code/ryzom/client/src/interface_v3/interface_manager.h
index 2171ecb4c..d70a1def9 100644
--- a/code/ryzom/client/src/interface_v3/interface_manager.h
+++ b/code/ryzom/client/src/interface_v3/interface_manager.h
@@ -30,7 +30,7 @@
 #include "view_pointer.h"
 
 #include "nel/gui/ctrl_base.h"
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 
 #include "nel/gui/view_renderer.h"
 
diff --git a/code/ryzom/client/src/interface_v3/interface_parser.cpp b/code/ryzom/client/src/interface_v3/interface_parser.cpp
index 73d1208b8..eba6b9094 100644
--- a/code/ryzom/client/src/interface_v3/interface_parser.cpp
+++ b/code/ryzom/client/src/interface_v3/interface_parser.cpp
@@ -52,7 +52,7 @@
 #include "dbview_quantity.h"
 #include "dbview_digit.h"
 // Ctrl
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 #include "nel/gui/ctrl_button.h"
 #include "ctrl_col_pick.h"
 #include "ctrl_tooltip.h"
diff --git a/code/ryzom/client/src/interface_v3/list_sheet_base.h b/code/ryzom/client/src/interface_v3/list_sheet_base.h
index 1ef13e4ca..609ee95ae 100644
--- a/code/ryzom/client/src/interface_v3/list_sheet_base.h
+++ b/code/ryzom/client/src/interface_v3/list_sheet_base.h
@@ -22,9 +22,12 @@
 #include "nel/misc/types_nl.h"
 #include "nel/gui/interface_group.h"
 
+namespace NLGUI
+{
+	class CCtrlScroll;
+}
 
 class	CDBCtrlSheet;
-class	CCtrlScroll;
 
 // ***************************************************************************
 /**
diff --git a/code/ryzom/client/src/interface_v3/register_interface_elements.cpp b/code/ryzom/client/src/interface_v3/register_interface_elements.cpp
index bb9d482a8..6a2e54483 100644
--- a/code/ryzom/client/src/interface_v3/register_interface_elements.cpp
+++ b/code/ryzom/client/src/interface_v3/register_interface_elements.cpp
@@ -24,6 +24,7 @@
 #include "view_text_id.h"
 #include "view_bitmap.h"
 #include "view_radar.h"
+#include "nel/gui/group_submenu_base.h"
 #include "group_menu.h"
 #include "nel/gui/ctrl_base.h"
 #include "nel/gui/interface_group.h"
@@ -46,7 +47,7 @@
 #include "dbview_bar3.h"
 #include "group_list.h"
 #include "nel/gui/ctrl_scroll_base.h"
-#include "ctrl_scroll.h"
+#include "nel/gui/ctrl_scroll.h"
 #include "dbgroup_combo_box.h"
 #include "group_tab.h"
 #include "group_html.h"
@@ -94,7 +95,8 @@ void registerInterfaceElements()
 	REGISTER_REFLECTABLE_CLASS(CCtrlScrollBase, CCtrlBase);
 	REGISTER_REFLECTABLE_CLASS(CCtrlScroll, CCtrlScrollBase);
 	REGISTER_REFLECTABLE_CLASS(CGroupMenu, CGroupModal)
-	REGISTER_REFLECTABLE_CLASS(CGroupSubMenu, CGroupFrame)
+	REGISTER_REFLECTABLE_CLASS(CGroupSubMenuBase, CGroupFrame)
+	REGISTER_REFLECTABLE_CLASS(CGroupSubMenu, CGroupSubMenuBase)
 	REGISTER_REFLECTABLE_CLASS(CGroupTab, CInterfaceGroup)
 	REGISTER_REFLECTABLE_CLASS(CGroupScrollText, CInterfaceGroup)
 	REGISTER_REFLECTABLE_CLASS(CGroupHTML, CGroupScrollText)
diff --git a/code/ryzom/client/src/libwww.h b/code/ryzom/client/src/libwww.h
index ec1462bc9..b82a75534 100644
--- a/code/ryzom/client/src/libwww.h
+++ b/code/ryzom/client/src/libwww.h
@@ -28,10 +28,10 @@ extern "C"
 namespace NLGUI
 {
 	class CCtrlBaseButton;
+	class CCtrlScroll;
 }
 
 class CGroupList;
-class CCtrlScroll;
 
 // ***************************************************************************