khanat-code-old/code/ryzom/client/src/interface_v3/interface_group.cpp

1970 lines
58 KiB
C++

// 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 "stdpch.h"
#include "interface_group.h"
#include "interface_manager.h"
#include "game_share/xml_auto_ptr.h"
#include "group_container.h"
#include "group_editbox.h"
#include "group_scrolltext.h"
#include "lua_ihm.h"
#include "nel/misc/stream.h"
using namespace std;
using namespace NL3D;
#define IG_UNIQUE_ID(this) ((void*)&((this)->_GroupSizeRef)) // NB nico : use some pointer *inside* CInterfaceGroup as a unique id for lua registry (any field but
// the first), instead of using 'this'. 'this' is already used by
// CLuaIHM::pushReflectableOnStack as unique id to CInterfaceElement's ref pointers
REGISTER_UI_CLASS(CInterfaceGroup)
// ------------------------------------------------------------------------------------------------
NLMISC_REGISTER_OBJECT(CViewBase, CInterfaceGroup, std::string, "interface_group");
CInterfaceGroup::CInterfaceGroup(const TCtorParam &param) : CCtrlBase(param)
{
_ParentSizeMax = NULL;
_MaxW = _MaxH = 16384;
_OffsetX = _OffsetY = 0;
_Overlappable= true;
_ResizeFromChildW= false;
_ResizeFromChildH= false;
_ResizeFromChildWMargin= 0;
_ResizeFromChildHMargin= 0;
_MaxWReal = _MaxHReal = 16384;
_GroupSizeRef = 0;
_Escapable= false;
_Priority= WIN_PRIORITY_NORMAL;
_UseCursor = true;
_IsGroupContainer = false;
_AHOnActive = NULL;
_AHOnDeactive = NULL;
_AHOnLeftClick = NULL;
_AHOnRightClick = NULL;
_AHOnEnter = NULL;
_AHOnEscape = NULL;
_NeedFrameUpdatePos= false;
_LUAEnvTableCreated= false;
#ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
CInterfaceManager::getInstance()->DebugTrackGroupsCreated( this );
#endif
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setIdRecurse(const std::string &id)
{
CCtrlBase::setIdRecurse(id);
for(std::vector<CInterfaceGroup*>::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it)
{
(*it)->setIdRecurse((*it)->getShortId());
}
for(std::vector<CCtrlBase*>::iterator it = _Controls.begin(); it != _Controls.end(); ++it)
{
(*it)->setIdRecurse((*it)->getShortId());
}
for(std::vector<CViewBase*>::iterator it = _Views.begin(); it != _Views.end(); ++it)
{
(*it)->setIdRecurse((*it)->getShortId());
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::notifyActiveCalled(const CEventDescriptorActiveCalledOnParent &desc)
{
// notify children that the 'active' state of this group has changed
for(std::vector<CInterfaceGroup*>::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it)
{
(*it)->handleEvent(desc);
}
for(std::vector<CCtrlBase*>::iterator ctrlIt = _Controls.begin(); ctrlIt != _Controls.end(); ++ctrlIt)
{
(*ctrlIt)->handleEvent(desc);
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setActive(bool state)
{
if(state != getActive())
{
CCtrlBase::setActive(state);
CInterfaceManager *pIM = CInterfaceManager::getInstance();
if (_AHOnActive != NULL && state)
{
pIM->runActionHandler (_AHOnActive, this, _AHOnActiveParams);
}
if (_AHOnDeactive != NULL && !state)
{
pIM->runActionHandler (_AHOnDeactive, this, _AHOnDeactiveParams);
}
notifyActiveCalled(CEventDescriptorActiveCalledOnParent(state));
}
}
// ------------------------------------------------------------------------------------------------
CInterfaceGroup::~CInterfaceGroup()
{
// delete any LUA group environnement
deleteLUAEnvTable();
// delete any LUA interface link "ondbchange"
removeAllLUAOnDbChange();
// NLMISC::TTime initStart;
// initStart = ryzomGetLocalTime ();
clearGroups();
// nlinfo ("%d seconds for clearGroups '%s'", (uint32)(ryzomGetLocalTime ()-initStart)/1000, _Id.c_str());
// initStart = ryzomGetLocalTime ();
clearViews();
// nlinfo ("%d seconds for clearViews '%s'", (uint32)(ryzomGetLocalTime ()-initStart)/1000, _Id.c_str());
// initStart = ryzomGetLocalTime ();
clearControls();
// nlinfo ("%d seconds for clearControls '%s'", (uint32)(ryzomGetLocalTime ()-initStart)/1000, _Id.c_str());
CInterfaceManager *manager = CInterfaceManager::getInstance();
manager->removeRefOnGroup (this);
#ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
// AJM DEBUG
CInterfaceManager::getInstance()->DebugTrackGroupsDestroyed( this );
#endif
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::clearViews()
{
// Yoyo: important to not Leave NULL in the array, because of ~CGroupHTML and LibWWW callback
// that may call CInterfaceManager::getElementFromId() (and this method hates having NULL in the arrays ^^)
while(!_Views.empty())
{
CViewBase *pVB = _Views.back();
delEltOrder (pVB);
delete pVB;
// slower than a _Views.clear() out of loop, but we have to keep a clean array.
_Views.pop_back();
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::clearControls()
{
// Yoyo: important to not Leave NULL in the array, because of ~CGroupHTML() and LibWWW callback
// that may call CInterfaceManager::getElementFromId() (and this method hates having NULL in the arrays ^^)
while(!_Controls.empty())
{
CCtrlBase *pCB = _Controls.back();
delEltOrder (pCB);
delete pCB;
// slower than a _Controls.clear() out of loop, but we have to keep a clean array.
_Controls.pop_back();
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::clearGroups()
{
// Yoyo: important to not Leave NULL in the array, because of ~CGroupHTML() and LibWWW callback
// that may call CInterfaceManager::getElementFromId() (and this method hates having NULL in the arrays ^^)
while(!_ChildrenGroups.empty())
{
CInterfaceGroup *pIG = _ChildrenGroups.back();
delEltOrder (pIG);
delete pIG;
// slower than a _ChildrenGroups.clear() out of loop, but we have to keep a clean array.
_ChildrenGroups.pop_back();
}
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::moveSBTrackY (CInterfaceGroup *target, sint32 dy)
{
// Look if there is a vertical scrollbar with this target attached ...
vector<CCtrlBase*>::iterator itc;
for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
{
CCtrlBase *pCB = *itc;
CCtrlScroll *pSB = dynamic_cast<CCtrlScroll*>(pCB);
if (pSB != NULL)
{
if (pSB->getTarget() == target)
{
pSB->moveTrackY(dy);
return true;
}
}
}
return false;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::moveSBTargetY(CInterfaceGroup *target,sint32 dy)
{
// Look if there is a vertical scrollbar with this target attached ...
vector<CCtrlBase*>::iterator itc;
for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
{
CCtrlBase *pCB = *itc;
CCtrlScroll *pSB = dynamic_cast<CCtrlScroll*>(pCB);
if (pSB != NULL)
{
if (pSB->getTarget() == target)
{
pSB->moveTargetY(dy);
return true;
}
}
}
return false;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setPriority(uint8 nprio)
{
if (nprio != _Priority)
{
CInterfaceManager::getInstance()->setWindowPriority(this, nprio);
}
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::parse (xmlNodePtr cur, CInterfaceGroup * parentGroup)
{
if ( !CCtrlBase::parse(cur,parentGroup) )
{
nlinfo ("cannot parse InterfaceElementLocalisable part");
return false;
}
//determine if the group is a window. If the property is not specified, set it to false.
CXMLAutoPtr ptr((const char*) xmlGetProp( cur, (xmlChar*)"win" ));
ptr = (char*) xmlGetProp( cur, (xmlChar*)"overlappable" );
if(ptr)
{
_Overlappable= convertBool(ptr);
}
ptr = (char*) xmlGetProp( cur, (xmlChar*)"escapable" );
if(ptr) _Escapable= convertBool(ptr);
// determine if the group must be sized according to his sons.
ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_w" );
if(ptr)
{
_ResizeFromChildW= convertBool(ptr);
}
ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_h" );
if(ptr)
{
_ResizeFromChildH= convertBool(ptr);
}
ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_wmargin" );
if(ptr)
{
NLMISC::fromString((const char*)ptr, _ResizeFromChildWMargin);
}
ptr = (char*) xmlGetProp( cur, (xmlChar*)"child_resize_hmargin" );
if(ptr)
{
NLMISC::fromString((const char*)ptr, _ResizeFromChildHMargin);
}
parseAH(cur, "on_active", "on_active_params", _AHOnActive, _AHOnActiveParams);
parseAH(cur, "on_deactive", "on_deactive_params", _AHOnDeactive, _AHOnDeactiveParams);
// Read user max size
ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_w" );
if (ptr) NLMISC::fromString((const char*)ptr, _MaxW);
ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_h" );
if (ptr) NLMISC::fromString((const char*)ptr, _MaxH);
ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_sizeref" );
if (ptr)
{
parseMaxSizeRef(ptr);
}
ptr = (char*) xmlGetProp( cur, (xmlChar*)"max_sizeparent" );
if (ptr)
{
string idparent = ptr;
idparent = NLMISC::strlwr(idparent);
if (idparent != "parent")
{
if (parentGroup)
idparent = parentGroup->getId() +":" + string((const char*)ptr);
else
idparent = "ui:" + string((const char*)ptr);
}
else
{
if (parentGroup)
idparent = parentGroup->getId();
}
CInterfaceManager::getInstance()->addParentSizeMaxAssociation (this, idparent);
}
// left & right clicks
parseAH(cur, "group_onclick_r", "group_params_r", _AHOnRightClick, _AHOnRightClickParams);
parseAH(cur, "group_onclick_l", "group_params_l", _AHOnLeftClick, _AHOnLeftClickParams);
// Each window (modal and groupContainer) can be validated by Enter. if "" => no op.
parseAH(cur, "on_enter", "on_enter_params", _AHOnEnter, _AHOnEnterParams);
ptr = (char*) xmlGetProp( cur, (xmlChar*)"win_priority" );
if(ptr) NLMISC::fromString((const char*)ptr, _Priority);
ptr = (char*) xmlGetProp( cur, (xmlChar*)"use_cursor" );
if(ptr) _UseCursor= convertBool(ptr);
// Each window (modal and groupContainer) can be escaped if "escapable" set
// they can add an action handler before the hide
parseAH(cur, "on_escape", "on_escape_params", _AHOnEscape, _AHOnEscapeParams);
// LuaClass script
ptr = xmlGetProp (cur, (xmlChar*)"lua_class");
if(ptr) CInterfaceManager::getInstance()->addLuaClassAssociation(this, (const char*)ptr);
return true;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::parseMaxSizeRef(const char *ptr)
{
parseSizeRef(ptr, _GroupSizeRef, _SizeDivW, _SizeDivH);
}
// ------------------------------------------------------------------------------------------------
uint32 CInterfaceGroup::getMemory ()
{
uint32 Mem = sizeof(*this);
/*vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin() ; itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pIG = *itg;
Mem += pIG->getMemory();
}*/
for (vector<CViewBase*>::const_iterator itv = _Views.begin() ; itv != _Views.end(); itv++)
{
CViewBase *pVB = *itv;
Mem += pVB->getMemory();
}
for (vector<CCtrlBase*>::const_iterator itc = _Controls.begin() ; itc != _Controls.end(); itc++)
{
CCtrlBase* ctrl = *itc;
Mem += ctrl->getMemory();
}
return Mem;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::addToEltOrder(CViewBase *view, sint order)
{
if (!view) return;
if (order == -1)
{
_EltOrder.push_back(view);
}
else
{
if (order > (sint) _EltOrder.size()) return;
_EltOrder.insert(_EltOrder.begin() + order, view);
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::addView (CViewBase *child, sint eltOrder /*= -1*/)
{
if (!child)
{
nlwarning("<CInterfaceGroup::addView> : tried to add a NULL view");
return;
}
_Views.push_back(child);
addToEltOrder(child, eltOrder);
// elt callBack.
child->onAddToGroup();
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::addCtrl (CCtrlBase *child, sint eltOrder /*= -1*/)
{
if (!child)
{
nlwarning("<CInterfaceGroup::addCtrl> : tried to add a NULL ctrl");
return;
}
_Controls.push_back(child);
addToEltOrder(child, eltOrder);
// elt callBack.
child->onAddToGroup();
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::addGroup (CInterfaceGroup *child, sint eltOrder /*= -1*/)
{
if (!child)
{
nlwarning("<CInterfaceGroup::addGroup> : tried to add a NULL group");
return;
}
_ChildrenGroups.push_back(child);
addToEltOrder(child, eltOrder);
// elt callBack.
child->onAddToGroup();
}
// ------------------------------------------------------------------------------------------------
int CInterfaceGroup::luaAddGroup (CLuaState &ls)
{
CLuaIHM::checkArgCount(ls, "CInterfaceGroup::addTab", 1);
CInterfaceGroup * group = dynamic_cast<CInterfaceGroup *>(CLuaIHM::getUIOnStack(ls, 1));
if(group)
{
group->setParent(this);
group->setParentPos(this);
addGroup(group);
}
return 0;
}
// ------------------------------------------------------------------------------------------------
// id = incomplete path (text:list:a) lid complete one (ui:interface:content:text:list:a)
static bool reverseCheckPath(const string &id, const string &lid)
{
string idTmp = id, lidTmp = lid;
// bool isFound = true;
while (idTmp.size() > 0)
{
string tokid, toklid;
string::size_type posid = idTmp.rfind (":");
if (posid == string::npos)
{
posid = 0;
tokid = idTmp;
}
else
{
tokid = idTmp.substr (posid+1);
}
string::size_type poslid = lidTmp.rfind (":");
if (poslid == string::npos)
{
poslid = 0;
toklid = lidTmp;
}
else
{
toklid = lidTmp.substr (poslid+1);
}
if (tokid != toklid)
return false;
if (posid > 0)
idTmp = idTmp.substr (0, posid);
else
idTmp = "";
if (poslid > 0)
lidTmp = lidTmp.substr (0, poslid);
else
lidTmp = "";
}
return true;
}
// ------------------------------------------------------------------------------------------------
CViewBase* CInterfaceGroup::getView (const std::string &id)
{
vector<CViewBase*>::const_iterator itv;
for (itv = _Views.begin(); itv != _Views.end(); ++itv)
{
CViewBase *pVB = (*itv);
if (reverseCheckPath(id, pVB->getId()))
return *itv;
}
// search in sons
std::vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); ++itg)
{
CViewBase* view = (*itg)->getView(id);
if (view)
return view;
}
return NULL;
}
// ------------------------------------------------------------------------------------------------
CCtrlBase* CInterfaceGroup::getCtrl (const std::string &id)
{
vector<CCtrlBase*>::const_iterator itv;
for (itv = _Controls.begin(); itv != _Controls.end(); ++itv)
{
CCtrlBase *pCB = (*itv);
if (reverseCheckPath(id, pCB->getId()))
return *itv;
}
// search in sons
std::vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); ++itg)
{
CCtrlBase*pCtrl = (*itg)->getCtrl (id);
if (pCtrl)
return pCtrl;
}
return NULL;
}
// ------------------------------------------------------------------------------------------------
CInterfaceGroup*CInterfaceGroup::getGroup (const std::string &id) const
{
std::vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end();itg++)
{
CInterfaceGroup *pIG = (*itg);
if (reverseCheckPath(id, pIG->getId()))
return *itg;
}
// search in sons
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); ++itg)
{
CInterfaceGroup *pCtrl = (*itg)->getGroup (id);
if (pCtrl)
return pCtrl;
}
return NULL;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delView (CViewBase *child, bool dontDelete /* = false*/)
{
for (sint32 i = 0; i < (sint32)_Views.size(); ++i)
{
if (_Views[i] == child)
{
if (!dontDelete) delete _Views[i];
_Views.erase(_Views.begin()+i);
delEltOrder (child);
return true;
}
}
return false;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delCtrl (CCtrlBase *child, bool dontDelete /* = false*/)
{
for (sint32 i = 0; i < (sint32)_Controls.size(); ++i)
{
if (_Controls[i] == child)
{
if (!dontDelete) delete _Controls[i];
_Controls.erase(_Controls.begin()+i);
delEltOrder (child);
return true;
}
}
return false;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delGroup (CInterfaceGroup *child, bool dontDelete /* = false*/)
{
for (sint32 i = 0; i < (sint32)_ChildrenGroups.size(); ++i)
{
if (_ChildrenGroups[i] == child)
{
if (!dontDelete) delete _ChildrenGroups[i];
_ChildrenGroups.erase(_ChildrenGroups.begin()+i);
delEltOrder (child);
return true;
}
}
return false;
}
// ------------------------------------------------------------------------------------------------
int CInterfaceGroup::luaDelGroup (CLuaState &ls)
{
CLuaIHM::checkArgCount(ls, "CInterfaceGroup::delTab", 1);
CInterfaceGroup * group = dynamic_cast<CInterfaceGroup *>(CLuaIHM::getUIOnStack(ls, 1));
if(group)
{
delGroup(group);
}
return 0;
}
// ------------------------------------------------------------------------------------------------
int CInterfaceGroup::luaGetNumGroups(CLuaState &ls)
{
CLuaIHM::checkArgCount(ls, "CInterfaceGroup::getNumGroups", 0);
ls.push((double) _ChildrenGroups.size());
return 1;
}
// ------------------------------------------------------------------------------------------------
int CInterfaceGroup::luaGetGroup(CLuaState &ls)
{
const char *funcName = "CInterfaceGroup::getGroup";
CLuaIHM::checkArgCount(ls, "CInterfaceGroup::getGroup", 1);
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER);
uint index = (uint) ls.toNumber(1);
if (index >= _ChildrenGroups.size())
{
CLuaIHM::fails(ls, "getGroup : try to index group %s, but there are only %d son groups", ls.toString(1), (int) _ChildrenGroups.size());
}
CLuaIHM::pushUIOnStack(ls, _ChildrenGroups[index]);
return 1;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::delEltOrder (CViewBase *pElt)
{
for (sint32 i = 0; i < (sint32)_EltOrder.size(); ++i)
{
if (_EltOrder[i] == pElt)
{
_EltOrder.erase (_EltOrder.begin()+i);
return;
}
}
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delView (const std::string &id, bool dontDelete /* = false*/)
{
return delView(getView(id), dontDelete);
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delCtrl (const std::string &id, bool dontDelete /* = false*/)
{
return delCtrl(getCtrl(id), dontDelete);
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delGroup (const std::string &id, bool dontDelete /* = false*/)
{
return delGroup(getGroup(id), dontDelete);
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::isChildGroup(const CInterfaceGroup *group) const
{
return std::find(_ChildrenGroups.begin(), _ChildrenGroups.end(), group) != _ChildrenGroups.end();
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::handleEvent (const CEventDescriptor &event)
{
if (CCtrlBase::handleEvent(event)) return true;
if (!_Active)
return false;
CInterfaceManager *im = CInterfaceManager::getInstance();
if (event.getType() == CEventDescriptor::system)
{
CEventDescriptorSystem &eds = (CEventDescriptorSystem&)event;
if (eds.getEventTypeExtended() == CEventDescriptorSystem::activecalledonparent)
{
// notify all childrens
notifyActiveCalled((CEventDescriptorActiveCalledOnParent &) eds);
}
}
if (event.getType() == CEventDescriptor::mouse)
{
const CEventDescriptorMouse &eventDesc = (const CEventDescriptorMouse &)event;
if (!isIn(eventDesc.getX(), eventDesc.getY()))
return false;
bool taken = false;
// For each control in the group...
vector<CCtrlBase*>::const_iterator itc;
for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
{
CCtrlBase *pCB = *itc;
if (pCB->getActive())
taken = taken || pCB->handleEvent(eventDesc);
}
if (taken)
return true;
// For each child group
for (sint i = (sint)_ChildrenGroups.size()-1; i >= 0; --i)
{
CInterfaceGroup *pIG = _ChildrenGroups[i];
if (pIG->getActive())
if (pIG->handleEvent(eventDesc))
return true;
}
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown)
{
if (_AHOnLeftClick != NULL)
{
im->runActionHandler(_AHOnLeftClick, this, _AHOnLeftClickParams);
return true;
}
}
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup)
{
if (_AHOnRightClick != NULL)
{
im->runActionHandler(_AHOnRightClick, this, _AHOnRightClickParams);
return true;
}
}
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mousewheel)
{
// handle the Mouse Wheel only if interesting
if (_H>_MaxH)
{
CInterfaceGroup *currParent = _Parent;
while (currParent)
{
if (currParent->moveSBTrackY (this, eventDesc.getWheel()*12))
return true;
currParent = currParent->getParent();
}
}
}
}
return false;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::executeControl (const std::string &/* sControlName */)
{
// bool taken = false;
// CCtrlBase *pIC = getCtrl (sControlName);
// if (pIC != NULL)
// pIC->callback(taken);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::draw ()
{
sint32 oldSciX, oldSciY, oldSciW, oldSciH;
makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
// Display sons only if not total clipped
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
if( !rVR.isClipWindowEmpty() )
{
// Draw all decorative elements
vector<CViewBase*>::const_iterator ite;
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{
CViewBase *pVB = *ite;
if (pVB->getActive())
pVB->draw();
}
}
restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::drawNoClip()
{
// Display sons only if not total clipped
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
if( !rVR.isClipWindowEmpty() )
{
// Draw all decorative elements
vector<CViewBase*>::const_iterator ite;
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{
CViewBase *pVB = *ite;
if (pVB->getActive())
pVB->draw();
}
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::renderWiredQuads(CInterfaceElement::TRenderWired type, const std::string &uiFilter)
{
if (!_Active) return;
CInterfaceElement::renderWiredQuads(type, uiFilter);
sint32 oldSciX, oldSciY, oldSciW, oldSciH;
makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
for(std::vector<CViewBase*>::iterator it = _EltOrder.begin(); it != _EltOrder.end(); ++it)
{
if (*it) (*it)->renderWiredQuads(type, uiFilter);
}
restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::drawElement (CViewBase *el)
{
sint32 oldSciX, oldSciY, oldSciW, oldSciH;
makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
if(el)
el->draw();
restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::checkCoords()
{
//update all children elements
vector<CViewBase*>::const_iterator ite;
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{
CViewBase *pIE = *ite;
if(pIE->getActive())
pIE->checkCoords();
}
executeLuaScriptOnDraw();
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::executeLuaScriptOnDraw()
{
// If some LUA script attached to me, execute it
if(!_LUAOnDraw.empty())
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
pIM->runActionHandler("lua", this, _LUAOnDraw);
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::doUpdateCoords()
{
_MaxWReal = _MaxW;
_MaxHReal = _MaxH;
CInterfaceElement *el = NULL;
if (_ParentSizeMax != NULL)
{
el = _ParentSizeMax;
}
else
{
if (_ParentSize != NULL)
{
el = _ParentSize;
}
else
{
if (_ParentPos != NULL)
el = _ParentPos;
else
el = _Parent;
}
}
if (el != NULL)
{
if (_GroupSizeRef&1)
_MaxWReal += _SizeDivW * el->getWReal() / 10;
if (_GroupSizeRef&2)
_MaxHReal += _SizeDivH * el->getHReal() / 10;
}
CViewBase::updateCoords();
_XReal += _OffsetX;
_YReal += _OffsetY;
//update all children elements
vector<CViewBase*>::const_iterator ite;
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{
CViewBase *pIE = *ite;
pIE->updateCoords();
}
_XReal -= _OffsetX;
_YReal -= _OffsetY;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::updateCoords()
{
// update basis and sons one time.
doUpdateCoords();
// if the group must resize from children
if(_ResizeFromChildH || _ResizeFromChildW)
{
// compute BBox of all childrens
sint width, height;
evalChildrenBBox(_ResizeFromChildW, _ResizeFromChildH, width, height);
// set forced size.
if(_ResizeFromChildW)
{
_W= _ResizeFromChildWMargin + width;
}
if(_ResizeFromChildH)
{
_H= _ResizeFromChildHMargin + height;
}
}
CInterfaceElement::updateCoords();
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::evalChildrenBBox(bool resizeFromChildW, bool resizeFromChildH, sint &width, sint &height) const
{
sint yMin=INT_MAX, yMax=INT_MIN;
sint xMin=INT_MAX, xMax=INT_MIN;
vector<CViewBase*>::const_iterator ite;
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{
CViewBase *pIE = *ite;
if (pIE->getActive())
{
const CInterfaceElement *el = pIE->getParentPos() ? pIE->getParentPos() : pIE->getParent();
if (el == this)
{
// to compute the bbox, don't use direct sons that have a sizeref on the resizing coordinate
if ((resizeFromChildW && (pIE->getSizeRef() & 1))
|| (resizeFromChildH && (pIE->getSizeRef() & 2))
)
{
continue;
}
}
// avoid also some interface elements
if(pIE->avoidResizeParent())
continue;
// get the real coords bounds.
sint32 x0,y0,x1,y1;
// If it is a group, minimize with MaxHReal / MaxWReal
const CInterfaceGroup *sonGroup= dynamic_cast<const CInterfaceGroup*>(pIE);
// \todo yoyo: do not know why but don't work if this==scroll_text
if(sonGroup && !dynamic_cast<const CGroupScrollText*>(this))
{
sint32 oldSciX= -16384;
sint32 oldSciY= -16384;
sint32 oldSciW= 32768;
sint32 oldSciH= 32768;
sint32 w, h;
sonGroup->computeCurrentClipContribution(oldSciX, oldSciY, oldSciW, oldSciH, x0, y0, w, h);
x1= x0 + w;
y1= y0 + h;
}
else
{
x0= pIE->getXReal();
y0= pIE->getYReal();
x1= x0 + pIE->getWReal();
y1= y0 + pIE->getHReal();
}
// enlarge
if(x0<xMin)
xMin= x0;
if(y0<yMin)
yMin= y0;
if(x1>xMax)
xMax= x1;
if(y1>yMax)
yMax= y1;
}
}
width = xMax - xMin;
height = yMax - yMin;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::invalidateTexts (bool resetTextIndex)
{
vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin() ; itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pIG = *itg;
pIG->invalidateTexts(resetTextIndex);
}
for (vector<CViewBase*>::const_iterator itv = _Views.begin() ; itv != _Views.end(); itv++)
{
CViewBase *pVB = *itv;
CViewText *pVT = dynamic_cast<CViewText*>(pVB);
if (pVT != NULL)
{
if (resetTextIndex)
pVT->resetTextIndex();
pVT->updateTextContext ();
}
}
}
// ------------------------------------------------------------------------------------------------
CInterfaceElement* CInterfaceGroup::getElement (const std::string &id)
{
if (_Id == id)
return this;
if (id.compare(0, _Id.size(), _Id) != 0)
return NULL;
vector<CViewBase*>::const_iterator itv;
for (itv = _Views.begin(); itv != _Views.end(); itv++)
{
CViewBase *pVB = *itv;
#if !FINAL_VERSION // For SpeedUp in final version
nlassert(pVB); // The element must not be NULL
#endif
if (pVB->getId() == id)
return pVB;
}
vector<CCtrlBase*>::const_iterator itc;
for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
{
CCtrlBase* ctrl = *itc;
#if !FINAL_VERSION // For SpeedUp in final version
nlassert(ctrl); // The element must not be NULL
#endif
if (ctrl->getId() == id)
return ctrl;
}
vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pIG = *itg;
#if !FINAL_VERSION // For SpeedUp in final version
nlassert(pIG); // The element must not be NULL
#endif
CInterfaceElement *pIEL = pIG->getElement(id);
if (pIEL != NULL)
return pIEL;
}
return NULL;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delElement (const std::string &id, bool noWarning)
{
if (id.substr(0, _Id.size()) != _Id)
return false;
vector<CViewBase*>::const_iterator itv;
for (itv = _Views.begin(); itv != _Views.end(); itv++)
{
CViewBase *pVB = *itv;
if (pVB->getId() == id)
{
delView (pVB, false);
return true;
}
}
vector<CCtrlBase*>::const_iterator itc;
for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
{
CCtrlBase* ctrl = *itc;
if (ctrl->getId() == id)
{
delCtrl (ctrl, false);
return true;
}
}
vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pIG = *itg;
if (pIG->getId() == id)
{
// If this is a root window
if (pIG->getRootWindow () == pIG)
CInterfaceManager::getInstance()->unMakeWindow(pIG, noWarning);
delGroup (pIG, false);
return true;
}
}
return false;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::delElement (CInterfaceElement *pIE, bool noWarning)
{
// delete correct type of element
if(pIE->isGroup())
{
CInterfaceGroup *pIG= static_cast<CInterfaceGroup*>(pIE);
// unmake window if it is
if (pIG->getRootWindow () == pIG)
CInterfaceManager::getInstance()->unMakeWindow(pIG, noWarning);
return delGroup(pIG);
}
else if(pIE->isCtrl())
{
return delCtrl(static_cast<CCtrlBase*>(pIE));
}
nlassert(pIE->isView());
return delView(static_cast<CViewBase*>(pIE));
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::isWindowUnder (sint32 x, sint32 y)
{
return ((x >= _XReal) &&
(x < (_XReal + _WReal))&&
(y > _YReal) &&
(y <= (_YReal + _HReal)));
}
// ------------------------------------------------------------------------------------------------
CInterfaceGroup* CInterfaceGroup::getGroupUnder (sint32 x, sint32 y)
{
// Begins by the children
std::vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pChild = *itg;
CInterfaceGroup *pChildUnder = pChild->getGroupUnder (x-_XReal, y-_YReal);
if (pChildUnder != NULL)
{
if ( (x >= _XReal) &&
(x < (_XReal + _WReal))&&
(y > _YReal) &&
(y <= (_YReal+ _HReal)))
return pChildUnder;
}
}
// If not found in childs then try in the parent one
if ( (x >= _XReal) &&
(x < (_XReal + _WReal))&&
(y > _YReal) &&
(y <= (_YReal+ _HReal)))
return this;
return NULL;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::getViewsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CViewBase*> &vVB)
{
if (!((x >= _XReal) &&
(x < (_XReal + _WReal))&&
(y > _YReal) &&
(y <= (_YReal+ _HReal))))
return false;
// test against current clip
computeCurrentClipContribution(clipX, clipY, clipW, clipH,
clipX, clipY, clipW, clipH);
if (!((x > clipX) &&
(x < (clipX + clipW))&&
(y > clipY) &&
(y < (clipY + clipH))))
return false;
// same as draw order: start with parent
std::vector<CViewBase*>::const_iterator itc;
for (itc = _EltOrder.begin(); itc != _EltOrder.end(); itc++)
{
if (!(*itc)->isCtrl() && !(*itc)->isGroup()) // must be a view
{
CViewBase *pVB = *itc;
if (pVB != NULL)
if (pVB->getActive())
if ( ((x) > pVB->getXReal()) &&
((x) < (pVB->getXReal() + pVB->getWReal()))&&
((y) > pVB->getYReal()) &&
((y) < (pVB->getYReal() + pVB->getHReal())))
{
vVB.push_back (pVB);
}
}
}
// same as draw order: continue with children
std::vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pChild = *itg;
if (pChild->getActive())
{
// bool bUnder =
pChild->getViewsUnder (x, y, clipX, clipY, clipW, clipH, vVB);
// if (bUnder && (vICL.size() > 0))
// return true;
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::getCtrlsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CCtrlBase*> &vICL)
{
if (!((x >= _XReal) &&
(x < (_XReal + _WReal))&&
(y > _YReal) &&
(y <= (_YReal+ _HReal))))
return false;
// test against current clip
computeCurrentClipContribution(clipX, clipY, clipW, clipH,
clipX, clipY, clipW, clipH);
if (!((x >= clipX) &&
(x < (clipX + clipW))&&
(y > clipY) &&
(y <= (clipY + clipH))))
return false;
// same as draw order: start with parent
std::vector<CViewBase*>::const_iterator itc;
for (itc = _EltOrder.begin(); itc != _EltOrder.end(); itc++)
{
if ((*itc)->isCtrl() && !(*itc)->isGroup()) // must be a ctrl but not a group (parsed later)
{
CCtrlBase *pICL = (CCtrlBase *) *itc;
if (pICL != NULL)
if (pICL->getActive())
if ( ((x) >= pICL->getXReal()) &&
((x) < (pICL->getXReal() + pICL->getWReal()))&&
((y) > pICL->getYReal()) &&
((y) <= (pICL->getYReal() + pICL->getHReal())))
{
vICL.push_back (pICL->getSubCtrl(x,y));
}
}
}
// same as draw order: continue with children
std::vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pChild = *itg;
if (pChild->getActive())
{
// bool bUnder =
pChild->getCtrlsUnder (x, y, clipX, clipY, clipW, clipH, vICL);
// if (bUnder && (vICL.size() > 0))
// return true;
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::getGroupsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CInterfaceGroup *> &vIGL)
{
if (!((x >= _XReal) &&
(x < (_XReal + _WReal))&&
(y > _YReal) &&
(y <= (_YReal+ _HReal))))
return false;
// test against current clip
computeCurrentClipContribution(clipX, clipY, clipW, clipH,
clipX, clipY, clipW, clipH);
if (!((x >= clipX) &&
(x < (clipX + clipW))&&
(y > clipY) &&
(y <= (clipY + clipH))))
return false;
// same as draw order: start with parent
std::vector<CViewBase*>::const_iterator itc;
for (itc = _EltOrder.begin(); itc != _EltOrder.end(); itc++)
{
if ((*itc)->isGroup()) // must be a group
{
CInterfaceGroup *pIGL = (CInterfaceGroup *) *itc;
if (pIGL != NULL)
if (pIGL->getActive())
if ( ((x) >= pIGL->getXReal()) &&
((x) < (pIGL->getXReal() + pIGL->getWReal()))&&
((y) > pIGL->getYReal()) &&
((y) <= (pIGL->getYReal() + pIGL->getHReal())))
{
vIGL.push_back (pIGL);
}
}
}
// same as draw order: continue with children
std::vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pChild = *itg;
if (pChild->getActive())
{
// bool bUnder =
pChild->getGroupsUnder (x, y, clipX, clipY, clipW, clipH, vIGL);
// if (bUnder && (vICL.size() > 0))
// return true;
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::absoluteToRelative (sint32 &x, sint32 &y)
{
CInterfaceGroup *curGrp = _Parent;
while (curGrp != NULL)
{
x = x - curGrp->_XReal;
y = y - curGrp->_YReal;
curGrp = curGrp->_Parent;
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::computeCurrentClipContribution(sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH,
sint32 &newSciXDest, sint32 &newSciYDest, sint32 &newSciWDest, sint32 &newSciHDest) const
{
sint32 newSciX = _XReal;
sint32 newSciY = _YReal;
sint32 newSciW = _WReal;
sint32 newSciH = _HReal;
// If there is width size limiter
if (_MaxWReal < _WReal)
{
if ((_PosRef == Hotspot_TR) || (_PosRef == Hotspot_MR) || (_PosRef == Hotspot_BR))
newSciX = _XReal + _WReal - _MaxWReal;
newSciW = _MaxWReal;
}
// If there is height size limiter
if (_MaxHReal < _HReal)
{
if ((_PosRef == Hotspot_TL) || (_PosRef == Hotspot_TM) || (_PosRef == Hotspot_TR))
newSciY = _YReal + _HReal - _MaxHReal;
newSciH = _MaxHReal;
}
// Clip Left
if (newSciX < oldSciX)
{
newSciW = newSciW - (oldSciX - newSciX);
newSciX = oldSciX;
}
// Clip Right
if ((newSciX+newSciW) > (oldSciX+oldSciW))
{
newSciW = newSciW - ((newSciX+newSciW)-(oldSciX+oldSciW));
}
// Clip Bottom
if (newSciY < oldSciY)
{
newSciH = newSciH - (oldSciY - newSciY);
newSciY = oldSciY;
}
// Clip Top
if ((newSciY+newSciH) > (oldSciY+oldSciH))
{
newSciH = newSciH - ((newSciY+newSciH)-(oldSciY+oldSciH));
}
newSciXDest = newSciX;
newSciYDest = newSciY;
newSciWDest = newSciW;
newSciHDest = newSciH;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH)
{
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
rVR.getClipWindow (oldSciX, oldSciY, oldSciW, oldSciH);
sint32 newSciX, newSciY, newSciW, newSciH;
computeCurrentClipContribution(oldSciX, oldSciY, oldSciW, oldSciH, newSciX, newSciY, newSciW, newSciH);
rVR.setClipWindow (newSciX, newSciY, newSciW, newSciH);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::getClip(sint32 &x, sint32 &y, sint32 &w, sint32 &h) const
{
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
uint32 sw, sh;
rVR.getScreenSize(sw, sh);
sint32 sciX = 0, sciY = 0, sciW = sw, sciH =sh;
const CInterfaceGroup *currGroup = this;
do
{
currGroup->computeCurrentClipContribution(sciX, sciY, sciW, sciH, sciX, sciY, sciW, sciH);
currGroup = currGroup->_Parent;
} while(currGroup);
x = sciX;
y = sciY;
w = sciW;
h = sciH;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::restoreClip (sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH)
{
CViewRenderer &rVR = CInterfaceManager::getInstance()->getViewRenderer();
rVR.setClipWindow (oldSciX, oldSciY, oldSciW, oldSciH);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::launch ()
{
// launch all elements
vector<CViewBase*>::const_iterator ite;
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{
CViewBase *pIE = *ite;
pIE->launch();
}
}
// ------------------------------------------------------------------------------------------------
CInterfaceGroup *CInterfaceGroup::getGroup(uint index) const
{
if (index > _ChildrenGroups.size())
{
nlwarning("<CInterfaceGroup::getGroup()> bad index;");
return NULL;
}
return _ChildrenGroups[index];
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::updateAllLinks()
{
CCtrlBase::updateAllLinks();
{
for(std::vector<CInterfaceGroup*>::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it)
{
(*it)->updateAllLinks();
}
}
{
for(std::vector<CCtrlBase*>::iterator it = _Controls.begin(); it != _Controls.end(); ++it)
{
(*it)->updateAllLinks();
}
}
{
for(std::vector<CViewBase*>::iterator it = _Views.begin(); it != _Views.end(); ++it)
{
(*it)->updateAllLinks();
}
}
}
// ------------------------------------------------------------------------------------------------
sint32 CInterfaceGroup::getAlpha() const
{
vector<CViewBase*>::const_iterator itv;
for (itv = _Views.begin(); itv != _Views.end(); itv++)
{
CViewBase *pVB = *itv;
sint32 a = pVB->getAlpha();
if (a != -1)
return a;
}
vector<CCtrlBase*>::const_iterator itc;
for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
{
CCtrlBase *pCB = *itc;
sint32 a = pCB->getAlpha();
if (a != -1)
return a;
}
vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pIG = *itg;
sint32 a = pIG->getAlpha();
if (a != -1)
return a;
}
return -1;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setAlpha (sint32 a)
{
vector<CViewBase*>::const_iterator itv;
for (itv = _Views.begin(); itv != _Views.end(); itv++)
{
CViewBase *pVB = *itv;
pVB->setAlpha(a);
}
vector<CCtrlBase*>::const_iterator itc;
for (itc = _Controls.begin(); itc != _Controls.end(); itc++)
{
CCtrlBase *pCB = *itc;
pCB->setAlpha(a);
}
vector<CInterfaceGroup*>::const_iterator itg;
for (itg = _ChildrenGroups.begin(); itg != _ChildrenGroups.end(); itg++)
{
CInterfaceGroup *pIG = *itg;
pIG->setAlpha(a);
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setLeftClickHandler(const std::string &handler)
{
_AHOnLeftClick = getAH(handler, _AHOnLeftClickParams);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setRightClickHandler(const std::string &handler)
{
_AHOnRightClick = getAH(handler, _AHOnRightClickParams);
}
// ------------------------------------------------------------------------------------------------
CGroupContainer *CInterfaceGroup::getEnclosingContainer()
{
CInterfaceGroup *ig = this;
do
{
if (ig->isGroupContainer()) return static_cast<CGroupContainer *>(ig);
ig = ig->getParent();
}
while(ig);
return NULL;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::dumpGroups()
{
nlinfo("Num groups = %d", (int) _ChildrenGroups.size());
for(uint k = 0; k < _ChildrenGroups.size(); ++k)
{
std::string typeName = "???";
if (_ChildrenGroups[k])
{
const type_info &ti = typeid(*_ChildrenGroups[k]);
typeName = ti.name();
}
nlinfo("Group %d, name = %s, type=%s", k, _ChildrenGroups[k] ? _ChildrenGroups[k]->getId().c_str() : "???", typeName.c_str());
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::dumpEltsOrder()
{
nlinfo("Num elements = %d", (int) _EltOrder.size());
for(uint k = 0; k < _EltOrder.size(); ++k)
{
std::string typeName = "???";
if (_ChildrenGroups[k])
{
const type_info &ti = typeid(*_EltOrder[k]);
typeName = ti.name();
}
CInterfaceElement *el = _EltOrder[k];
if (el)
{
nlinfo("Element %d, name = %s, type=%s, x=%d, y=%d, parent_name=%s parentposname=%s xreal=%d, yreal=%d, wreal=%d, hreal=%d",
k, el->getId().c_str(), typeName.c_str(), el->getX(), el->getY(), el->getParent() ? el->getParent()->getId().c_str() : "no parent",
el->getParentPos() ? el->getParentPos()->getId().c_str() : "parent",
(int) el->getXReal(),
(int) el->getYReal(),
(int) el->getWReal(),
(int) el->getHReal()
);
}
else
{
nlinfo("Element %d = NULL", (int) k);
}
}
}
// ------------------------------------------------------------------------------------------------
sint CInterfaceGroup::getInsertionOrder(CViewBase *vb) const
{
for(uint k = 0; k < _EltOrder.size(); ++k)
{
if (_EltOrder[k] == vb) return (sint) k;
}
return -1;
}
// ------------------------------------------------------------------------------------------------
sint32 CInterfaceGroup::getMaxUsedW() const
{
sint maxWidth = 0;
for (uint k = 0; k < _EltOrder.size(); ++k)
{
// Get the child width
sint32 width = _EltOrder[k]->getMaxUsedW()+_EltOrder[k]->getXReal() - getXReal();
if (width > maxWidth)
maxWidth = width;
}
return maxWidth;
}
// ------------------------------------------------------------------------------------------------
sint32 CInterfaceGroup::getMinUsedW() const
{
sint32 minWidth = 0;
for (uint k = 0; k < _EltOrder.size(); ++k)
{
// Get the child width
sint32 width = _EltOrder[k]->getMinUsedW()+_EltOrder[k]->getXReal() - getXReal();
if (width > minWidth)
minWidth = width;
}
return minWidth;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::clearAllEditBox()
{
for(uint k = 0; k < _ChildrenGroups.size(); ++k)
{
if (_ChildrenGroups[k]) _ChildrenGroups[k]->clearAllEditBox();
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::restoreAllContainersBackupPosition()
{
for(uint k = 0; k < _ChildrenGroups.size(); ++k)
{
if (_ChildrenGroups[k]) _ChildrenGroups[k]->restoreAllContainersBackupPosition();
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::dumpSize(uint depth /*=0*/) const
{
CViewBase::dumpSize(depth);
for(uint k = 0; k < _ChildrenGroups.size(); ++k)
{
_ChildrenGroups[k]->dumpSize(depth + 1);
}
for(uint k = 0; k < _Controls.size(); ++k)
{
_Controls[k]->dumpSize(depth + 1);
}
for(uint k = 0; k < _Views.size(); ++k)
{
_Views[k]->dumpSize(depth + 1);
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::visit(CInterfaceElementVisitor *visitor)
{
nlassert(visitor);
for(uint k = 0; k < _ChildrenGroups.size(); ++k)
{
_ChildrenGroups[k]->visit(visitor);
}
for(uint k = 0; k < _Controls.size(); ++k)
{
_Controls[k]->visit(visitor);
}
for(uint k = 0; k < _Views.size(); ++k)
{
_Views[k]->visit(visitor);
}
visitor->visitGroup(this);
CInterfaceElement::visit(visitor);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setUseCursor(bool use)
{
_UseCursor=use;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::onFrameUpdateWindowPos(sint dx, sint dy)
{
// Move me.
_XReal+= dx;
_YReal+= dy;
// Move all my sons.
vector<CViewBase*>::const_iterator ite;
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{
CViewBase *pIE = *ite;
pIE->onFrameUpdateWindowPos(dx, dy);
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::pushLUAEnvTable()
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CLuaState *lua= pIM->getLuaState();
nlassert(lua);
if(!_LUAEnvTableCreated)
{
CLuaStackChecker lsc(lua);
// Create a table and assign it in the REGISTRY."__ui_envtable" table, with a userdata ptr
lua->push(IHM_LUA_ENVTABLE);
lua->getTable(LUA_REGISTRYINDEX); // Stack: __ui_envtable
lua->pushLightUserData(IG_UNIQUE_ID(this));
lua->newTable();
lua->setTable(-3); // Stack: __ui_envtable (with .this={})
lua->pop();
// Created!
_LUAEnvTableCreated= true;
}
// Get the table from registry, and push it on stack
CLuaStackChecker lsc(lua, 1);
lua->push(IHM_LUA_ENVTABLE);
lua->getTable(LUA_REGISTRYINDEX); // __ui_envtable
lua->pushLightUserData(IG_UNIQUE_ID(this));
lua->getTable(-2); // __ui_envtable envtable
lua->remove(-2); // envtable
nlassert(lua->isTable());
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::deleteLUAEnvTable(bool recurse)
{
if(_LUAEnvTableCreated)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CLuaState *lua= pIM->getLuaState();
nlassert(lua);
// replace simply the table with Nil, letting LUA Garbage collector do the realease stuff
CLuaStackChecker lsc(lua);
lua->push(IHM_LUA_ENVTABLE);
lua->getTable(LUA_REGISTRYINDEX); // __ui_envtable
lua->pushLightUserData(IG_UNIQUE_ID(this)); // NB nico : use some pointer *inside* that object as a unique id (any field but
// the first), instead of using 'this'. 'this' is already used by
// CLuaIHM::pushReflectableOnStack
lua->pushNil();
lua->setTable(-3); // __ui_envtable
lua->pop();
_LUAEnvTableCreated= false;
}
if (recurse)
{
for(uint k = 0; k < _ChildrenGroups.size(); ++k)
{
_ChildrenGroups[k]->deleteLUAEnvTable(true);
}
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setLuaScriptOnDraw(const std::string &script)
{
_LUAOnDraw= script;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::addLuaScriptOnDBChange(const std::string &dbList, const std::string &script)
{
// remove any existing
removeLuaScriptOnDBChange(dbList);
// create and attach the link
NLMISC::CSmartPtr<CInterfaceLink> newLink= new CInterfaceLink;
_LUAOnDbChange[dbList]= newLink;
// Init and attach to list of untargeted links
std::vector<CInterfaceLink::CTargetInfo> noTargets;
newLink->init(noTargets, NLMISC::toString("depends(%s)", dbList.c_str()), "lua", script, "", this);
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::removeLuaScriptOnDBChange(const std::string &dbList)
{
TLUAOnDbChange::iterator it= _LUAOnDbChange.find(dbList);
if(it!=_LUAOnDbChange.end())
{
nlassert(it->second!=NULL);
// Remove from link of untargeted Links
it->second->uninit();
// erase from map (thus the ptr should be deleted)
_LUAOnDbChange.erase(it);
}
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::removeAllLUAOnDbChange()
{
TLUAOnDbChange::iterator it= _LUAOnDbChange.begin();
for(;it!=_LUAOnDbChange.end();)
{
// since deleted, must not do it++, but it= begin()
removeLuaScriptOnDBChange(it->first);
it= _LUAOnDbChange.begin();
}
}
// ------------------------------------------------------------------------------------------------
int CInterfaceGroup::luaFind(CLuaState &ls)
{
CLuaIHM::checkArgCount(ls, "CInterfaceGroup::find", 1);
CLuaIHM::checkArgType(ls, "CInterfaceGroup::find", 1, LUA_TSTRING);
std::string id = ls.toString(1);
CInterfaceElement* element = findFromShortId(id);
if (!element)
{
ls.pushNil();
}
else
{
CLuaIHM::pushUIOnStack(ls, element);
}
return 1;
}
// ------------------------------------------------------------------------------------------------
CInterfaceElement* CInterfaceGroup::findFromShortId(const std::string &id)
{
CInterfaceElement* element = NULL;
element = getView(id);
if (!element) element = getCtrl(id);
if (!element) element = getGroup(id);
return element;
}
// ------------------------------------------------------------------------------------------------
int CInterfaceGroup::luaGetEnclosingContainer(CLuaState &ls)
{
CLuaIHM::checkArgCount(ls, "CInterfaceGroup::getEnclosingContainer", 0);
CLuaIHM::pushUIOnStack(ls, getEnclosingContainer());
return 1;
}
// ------------------------------------------------------------------------------------------------
int CInterfaceGroup::luaDeleteLUAEnvTable(CLuaState &ls)
{
const char *funcName = "deleteLUAenvTable";
CLuaIHM::checkArgCount(ls, funcName, 1);
CLuaIHM::checkArgType(ls, funcName, 1, LUA_TBOOLEAN); // is delete recursive
deleteLUAEnvTable(ls.toBoolean(1));
return 0;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::serial(NLMISC::IStream &f)
{
CCtrlBase::serial(f);
f.serialContPolyPtr(_ChildrenGroups);
f.serialContPolyPtr(_Controls);
f.serialContPolyPtr(_Views);
f.serialContPolyPtr(_EltOrder);
f.serial(_MaxW, _MaxH);
f.serial(_MaxWReal, _MaxHReal);
f.serial(_OffsetX, _OffsetY);
f.serial(_Priority);
nlSerialBitBool(f, _Overlappable);
nlSerialBitBool(f, _ResizeFromChildW);
nlSerialBitBool(f, _ResizeFromChildH);
nlSerialBitBool(f, _Escapable);
nlSerialBitBool(f, _UseCursor);
nlSerialBitBool(f, _IsGroupContainer);
nlSerialBitBool(f, _NeedFrameUpdatePos);
f.serial(_ResizeFromChildWMargin);
f.serial(_ResizeFromChildHMargin);
f.serial(_GroupSizeRef);
serialAH(f, _AHOnActive);
f.serial(_AHOnActiveParams);
serialAH(f, _AHOnDeactive);
f.serial(_AHOnDeactiveParams);
// right & left clicks
serialAH(f, _AHOnLeftClick);
f.serial(_AHOnLeftClickParams);
serialAH(f, _AHOnRightClick);
f.serial(_AHOnRightClickParams);
// enter params.
serialAH(f, _AHOnEnter);
f.serial(_AHOnEnterParams);
// escape AH
serialAH(f, _AHOnEscape);
f.serial(_AHOnEscapeParams);
}
// ------------------------------------------------------------------------------------------------
CInterfaceElement *CInterfaceGroup::clone()
{
CInterfaceElement *oldParentSizeMax = _ParentSizeMax;
if (_ParentSizeMax == _Parent)
{
_ParentSizeMax = NULL;
}
CInterfaceElement *ret = CCtrlBase::clone();
_ParentSizeMax = oldParentSizeMax;
return ret;
}
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::setMaxSizeRef(const std::string &maxSizeRef)
{
parseMaxSizeRef(maxSizeRef.c_str());
}
// ------------------------------------------------------------------------------------------------
std::string CInterfaceGroup::getMaxSizeRefAsString() const
{
return "IMPLEMENT ME!";
}