// Ryzom - MMORPG Framework // 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 . #include "libxml/globals.h" #include "nel/misc/debug.h" #include "nel/misc/xml_auto_ptr.h" #include "nel/misc/stream.h" #include "nel/gui/lua_manager.h" #include "nel/gui/lua_ihm.h" #include "nel/gui/view_renderer.h" #include "nel/gui/interface_group.h" #include "nel/gui/interface_link.h" #include "nel/gui/widget_manager.h" #include "nel/gui/ctrl_scroll_base.h" #include "nel/gui/lua_ihm.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 namespace NLGUI { REGISTER_UI_CLASS(CInterfaceGroup) // ------------------------------------------------------------------------------------------------ NLMISC_REGISTER_OBJECT(CViewBase, CInterfaceGroup, std::string, "interface_group"); CInterfaceGroup::CInterfaceGroup(const TCtorParam ¶m) : 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; _IsGroupScrollText = false; _IsGroupInScene = false; _IsGroupList = false; _AHOnActive = NULL; _AHOnDeactive = NULL; _AHOnLeftClick = NULL; _AHOnRightClick = NULL; _AHOnEnter = NULL; _AHOnEscape = NULL; _NeedFrameUpdatePos= false; _LUAEnvTableCreated= false; _DepthForZSort= 0.f; #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS CInterfaceManager::getInstance()->DebugTrackGroupsCreated( this ); #endif } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::setIdRecurse(const std::string &id) { CCtrlBase::setIdRecurse(id); for(std::vector::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it) { (*it)->setIdRecurse((*it)->getShortId()); } for(std::vector::iterator it = _Controls.begin(); it != _Controls.end(); ++it) { (*it)->setIdRecurse((*it)->getShortId()); } for(std::vector::iterator it = _Views.begin(); it != _Views.end(); ++it) { (*it)->setIdRecurse((*it)->getShortId()); } } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::notifyActiveCalled(const NLGUI::CEventDescriptorActiveCalledOnParent &desc) { // notify children that the 'active' state of this group has changed for(std::vector::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it) { (*it)->handleEvent(desc); } for(std::vector::iterator ctrlIt = _Controls.begin(); ctrlIt != _Controls.end(); ++ctrlIt) { (*ctrlIt)->handleEvent(desc); } } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::setActive(bool state) { if(state != getActive()) { CCtrlBase::setActive(state); if (_AHOnActive != NULL && state) { CAHManager::getInstance()->runActionHandler (_AHOnActive, this, _AHOnActiveParams); } if (_AHOnDeactive != NULL && !state) { CAHManager::getInstance()->runActionHandler (_AHOnDeactive, this, _AHOnDeactiveParams); } notifyActiveCalled(NLGUI::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()); CWidgetManager::getInstance()->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::iterator itc; for (itc = _Controls.begin(); itc != _Controls.end(); itc++) { CCtrlBase *pCB = *itc; CCtrlScrollBase *pSB = dynamic_cast(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::iterator itc; for (itc = _Controls.begin(); itc != _Controls.end(); itc++) { CCtrlBase *pCB = *itc; CCtrlScrollBase *pSB = dynamic_cast(pCB); if (pSB != NULL) { if (pSB->getTarget() == target) { pSB->moveTargetY(dy); return true; } } } return false; } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::setPriority(uint8 nprio) { if (nprio != _Priority) { CWidgetManager::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); } CAHManager::getInstance()->parseAH(cur, "on_active", "on_active_params", _AHOnActive, _AHOnActiveParams); CAHManager::getInstance()->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(); } CWidgetManager::parser->addParentSizeMaxAssociation (this, idparent); } // left & right clicks CAHManager::getInstance()->parseAH(cur, "group_onclick_r", "group_params_r", _AHOnRightClick, _AHOnRightClickParams); CAHManager::getInstance()->parseAH(cur, "group_onclick_l", "group_params_l", _AHOnLeftClick, _AHOnLeftClickParams); // Each window (modal and groupContainer) can be validated by Enter. if "" => no op. CAHManager::getInstance()->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 CAHManager::getInstance()->parseAH(cur, "on_escape", "on_escape_params", _AHOnEscape, _AHOnEscapeParams); // LuaClass script ptr = xmlGetProp (cur, (xmlChar*)"lua_class"); if( ptr ) CWidgetManager::parser->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::const_iterator itg; for (itg = _ChildrenGroups.begin() ; itg != _ChildrenGroups.end(); itg++) { CInterfaceGroup *pIG = *itg; Mem += pIG->getMemory(); }*/ for (vector::const_iterator itv = _Views.begin() ; itv != _Views.end(); itv++) { CViewBase *pVB = *itv; Mem += pVB->getMemory(); } for (vector::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(" : 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(" : 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(" : 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(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::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::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::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::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::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(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 NLGUI::CEventDescriptor &event) { if (CCtrlBase::handleEvent(event)) return true; if (!_Active) return false; if (event.getType() == NLGUI::CEventDescriptor::system) { NLGUI::CEventDescriptorSystem &eds = (NLGUI::CEventDescriptorSystem&)event; if (eds.getEventTypeExtended() == NLGUI::CEventDescriptorSystem::activecalledonparent) { // notify all childrens notifyActiveCalled((NLGUI::CEventDescriptorActiveCalledOnParent &) eds); } } if (event.getType() == NLGUI::CEventDescriptor::mouse) { const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event; if (!isIn(eventDesc.getX(), eventDesc.getY())) return false; bool taken = false; // For each control in the group... vector::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() == NLGUI::CEventDescriptorMouse::mouseleftdown) { if (_AHOnLeftClick != NULL) { CAHManager::getInstance()->runActionHandler(_AHOnLeftClick, this, _AHOnLeftClickParams); return true; } } if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup) { if (_AHOnRightClick != NULL) { CAHManager::getInstance()->runActionHandler(_AHOnRightClick, this, _AHOnRightClickParams); return true; } } if (eventDesc.getEventTypeExtended() == NLGUI::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 = *CViewRenderer::getInstance(); if( !rVR.isClipWindowEmpty() ) { // Draw all decorative elements vector::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 = *CViewRenderer::getInstance(); if( !rVR.isClipWindowEmpty() ) { // Draw all decorative elements vector::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::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::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()) CAHManager::getInstance()->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::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::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(pIE); // \todo yoyo: do not know why but don't work if this==scroll_text if(sonGroup && !isGroupScrollText()) { 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(x0xMax) xMax= x1; if(y1>yMax) yMax= y1; } } width = xMax - xMin; height = yMax - yMin; } // ------------------------------------------------------------------------------------------------ CInterfaceElement* CInterfaceGroup::getElement (const std::string &id) { if (_Id == id) return this; if (id.compare(0, _Id.size(), _Id) != 0) return NULL; vector::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::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::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::const_iterator itv; for (itv = _Views.begin(); itv != _Views.end(); itv++) { CViewBase *pVB = *itv; if (pVB->getId() == id) { delView (pVB, false); return true; } } vector::const_iterator itc; for (itc = _Controls.begin(); itc != _Controls.end(); itc++) { CCtrlBase* ctrl = *itc; if (ctrl->getId() == id) { delCtrl (ctrl, false); return true; } } vector::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) CWidgetManager::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(pIE); // unmake window if it is if (pIG->getRootWindow () == pIG) CWidgetManager::getInstance()->unMakeWindow(pIG, noWarning); return delGroup(pIG); } else if(pIE->isCtrl()) { return delCtrl(static_cast(pIE)); } nlassert(pIE->isView()); return delView(static_cast(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::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 &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::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::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 &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::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::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 &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::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::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 = *CViewRenderer::getInstance(); 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 = *CViewRenderer::getInstance(); 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 = *CViewRenderer::getInstance(); rVR.setClipWindow (oldSciX, oldSciY, oldSciW, oldSciH); } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::launch () { // launch all elements vector::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(" bad index;"); return NULL; } return _ChildrenGroups[index]; } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::updateAllLinks() { CCtrlBase::updateAllLinks(); { for(std::vector::iterator it = _ChildrenGroups.begin(); it != _ChildrenGroups.end(); ++it) { (*it)->updateAllLinks(); } } { for(std::vector::iterator it = _Controls.begin(); it != _Controls.end(); ++it) { (*it)->updateAllLinks(); } } { for(std::vector::iterator it = _Views.begin(); it != _Views.end(); ++it) { (*it)->updateAllLinks(); } } } // ------------------------------------------------------------------------------------------------ sint32 CInterfaceGroup::getAlpha() const { vector::const_iterator itv; for (itv = _Views.begin(); itv != _Views.end(); itv++) { CViewBase *pVB = *itv; sint32 a = pVB->getAlpha(); if (a != -1) return a; } vector::const_iterator itc; for (itc = _Controls.begin(); itc != _Controls.end(); itc++) { CCtrlBase *pCB = *itc; sint32 a = pCB->getAlpha(); if (a != -1) return a; } vector::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::const_iterator itv; for (itv = _Views.begin(); itv != _Views.end(); itv++) { CViewBase *pVB = *itv; pVB->setAlpha(a); } vector::const_iterator itc; for (itc = _Controls.begin(); itc != _Controls.end(); itc++) { CCtrlBase *pCB = *itc; pCB->setAlpha(a); } vector::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 = CAHManager::getInstance()->getAH(handler, _AHOnLeftClickParams); } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::setRightClickHandler(const std::string &handler) { _AHOnRightClick = CAHManager::getInstance()->getAH(handler, _AHOnRightClickParams); } // ------------------------------------------------------------------------------------------------ CInterfaceGroup* CInterfaceGroup::getEnclosingContainer() { CInterfaceGroup *ig = this; do { if( ig->isGroupContainer() ) return ig; ig = ig->getParent(); } while( ig != NULL ); 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::visitGroupAndChildren( CInterfaceElementVisitor *visitor ) { nlassert( visitor != 0 ); for( uint i = 0; i < _ChildrenGroups.size(); i++ ) { _ChildrenGroups[ i ]->visitGroupAndChildren( visitor ); } visitor->visitGroup( this ); } // ------------------------------------------------------------------------------------------------ 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::const_iterator ite; for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++) { CViewBase *pIE = *ite; pIE->onFrameUpdateWindowPos(dx, dy); } } // ------------------------------------------------------------------------------------------------ void CInterfaceGroup::pushLUAEnvTable() { CLuaState *lua= CLuaManager::getInstance().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) { CLuaState *lua= CLuaManager::getInstance().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 newLink= new CInterfaceLink; _LUAOnDbChange[dbList]= newLink; // Init and attach to list of untargeted links std::vector 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!"; } }