Avoid having to use 'set' action handler, which parses the value expression on every use, in interface links by implementing use of cdb nodes as targets
This commit is contained in:
parent
22934d2b60
commit
b09e28e9e0
6 changed files with 119 additions and 9 deletions
|
@ -66,6 +66,11 @@ namespace NLGUI
|
||||||
*/
|
*/
|
||||||
bool affect(const CInterfaceExprValue &value);
|
bool affect(const CInterfaceExprValue &value);
|
||||||
};
|
};
|
||||||
|
struct CCDBTargetInfo
|
||||||
|
{
|
||||||
|
NLMISC::CRefPtr<NLMISC::CCDBNodeLeaf> Leaf;
|
||||||
|
std::string LeafName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Updates triggered interface links when triggered by the observed branch
|
/// Updates triggered interface links when triggered by the observed branch
|
||||||
|
@ -85,7 +90,7 @@ namespace NLGUI
|
||||||
* If there are no target element, the link is permanent (removed at exit)
|
* If there are no target element, the link is permanent (removed at exit)
|
||||||
* NB : The target is not updated during this call.
|
* NB : The target is not updated during this call.
|
||||||
*/
|
*/
|
||||||
bool init(const std::vector<CTargetInfo> &targets, const std::string &expr, const std::string &actionHandler, const std::string &ahParams, const std::string &ahCond, CInterfaceGroup *parent);
|
bool init(const std::vector<CTargetInfo> &targets, const std::vector<CCDBTargetInfo> &cdbTargets, const std::string &expr, const std::string &actionHandler, const std::string &ahParams, const std::string &ahCond, CInterfaceGroup *parent);
|
||||||
// force all the links that have been created to update their targets. This can be called when the interface has been loaded, and when the databse entries have been retrieved.
|
// force all the links that have been created to update their targets. This can be called when the interface has been loaded, and when the databse entries have been retrieved.
|
||||||
static void updateAllLinks();
|
static void updateAllLinks();
|
||||||
// force all trigered links to be updated
|
// force all trigered links to be updated
|
||||||
|
@ -119,6 +124,7 @@ namespace NLGUI
|
||||||
* \return true if all targets are valid
|
* \return true if all targets are valid
|
||||||
*/
|
*/
|
||||||
static bool splitLinkTargets(const std::string &targets, CInterfaceGroup *parentGroup, std::vector<CInterfaceLink::CTargetInfo> &targetsVect);
|
static bool splitLinkTargets(const std::string &targets, CInterfaceGroup *parentGroup, std::vector<CInterfaceLink::CTargetInfo> &targetsVect);
|
||||||
|
static bool splitLinkTargetsExt(const std::string &targets, CInterfaceGroup *parentGroup, std::vector<CInterfaceLink::CTargetInfo> &targetsVect, std::vector<CInterfaceLink::CCDBTargetInfo> &cdbTargetsVect);
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
private:
|
private:
|
||||||
friend struct CRemoveTargetPred;
|
friend struct CRemoveTargetPred;
|
||||||
|
@ -135,6 +141,7 @@ namespace NLGUI
|
||||||
typedef std::vector<NLMISC::ICDBNode *> TNodeVect;
|
typedef std::vector<NLMISC::ICDBNode *> TNodeVect;
|
||||||
private:
|
private:
|
||||||
std::vector<CTarget> _Targets;
|
std::vector<CTarget> _Targets;
|
||||||
|
std::vector<CCDBTargetInfo> _CDBTargets;
|
||||||
TNodeVect _ObservedNodes;
|
TNodeVect _ObservedNodes;
|
||||||
std::string _Expr;
|
std::string _Expr;
|
||||||
CInterfaceExprNode *_ParseTree;
|
CInterfaceExprNode *_ParseTree;
|
||||||
|
|
|
@ -2325,7 +2325,8 @@ namespace NLGUI
|
||||||
_LUAOnDbChange[dbList]= newLink;
|
_LUAOnDbChange[dbList]= newLink;
|
||||||
// Init and attach to list of untargeted links
|
// Init and attach to list of untargeted links
|
||||||
std::vector<CInterfaceLink::CTargetInfo> noTargets;
|
std::vector<CInterfaceLink::CTargetInfo> noTargets;
|
||||||
newLink->init(noTargets, NLMISC::toString("depends(%s)", dbList.c_str()), "lua", script, "", this);
|
std::vector<CInterfaceLink::CCDBTargetInfo> noCdbTargets;
|
||||||
|
newLink->init(noTargets, noCdbTargets, NLMISC::toString("depends(%s)", dbList.c_str()), "lua", script, "", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -194,7 +194,7 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================
|
//===========================================================
|
||||||
bool CInterfaceLink::init(const std::vector<CTargetInfo> &targets, const std::string &expr, const std::string &actionHandler, const std::string &ahParams, const std::string &ahCond, CInterfaceGroup *parentGroup)
|
bool CInterfaceLink::init(const std::vector<CTargetInfo> &targets, const std::vector<CCDBTargetInfo> &cdbTargets, const std::string &expr, const std::string &actionHandler, const std::string &ahParams, const std::string &ahCond, CInterfaceGroup *parentGroup)
|
||||||
{
|
{
|
||||||
CInterfaceExprValue result;
|
CInterfaceExprValue result;
|
||||||
// Build the parse tree
|
// Build the parse tree
|
||||||
|
@ -240,6 +240,7 @@ namespace NLGUI
|
||||||
// There are no target for this link, so, put in a dedicated list to ensure that the link will be destroyed at exit
|
// There are no target for this link, so, put in a dedicated list to ensure that the link will be destroyed at exit
|
||||||
_LinksWithNoTarget.push_back(TLinkSmartPtr(this));
|
_LinksWithNoTarget.push_back(TLinkSmartPtr(this));
|
||||||
}
|
}
|
||||||
|
_CDBTargets = cdbTargets;
|
||||||
|
|
||||||
// create observers
|
// create observers
|
||||||
createObservers(_ObservedNodes);
|
createObservers(_ObservedNodes);
|
||||||
|
@ -365,12 +366,41 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_CDBTargets.size())
|
||||||
|
{
|
||||||
|
CInterfaceExprValue resultCopy = result;
|
||||||
|
if (resultCopy.toInteger())
|
||||||
|
{
|
||||||
|
sint64 resultValue = resultCopy.getInteger();
|
||||||
|
for (uint k = 0; k < _CDBTargets.size(); ++k)
|
||||||
|
{
|
||||||
|
NLMISC::CCDBNodeLeaf *node = _CDBTargets[k].Leaf;
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
node = _CDBTargets[k].Leaf = NLGUI::CDBManager::getInstance()->getDbProp(_CDBTargets[k].LeafName, false);
|
||||||
|
}
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
// assuming setvalue64 always works
|
||||||
|
node->setValue64(resultValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("CInterfaceLink::update: Node does not exist: '%s'", _CDBTargets[k].LeafName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("CInterfaceLink::update: Result conversion to db target failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
// if there's an action handler, execute it
|
// if there's an action handler, execute it
|
||||||
if (!_ActionHandler.empty())
|
if (!_ActionHandler.empty())
|
||||||
{
|
{
|
||||||
// If there is a condition, test it.
|
// If there is a condition, test it.
|
||||||
bool launch = _AHCond.empty();
|
bool launch = _AHCond.empty();
|
||||||
if (_AHCondParsed)
|
if (_AHCondParsed) // todo: maybe makes more sense to make condition also cover target
|
||||||
{
|
{
|
||||||
CInterfaceExprValue result;
|
CInterfaceExprValue result;
|
||||||
_AHCondParsed->eval(result);
|
_AHCondParsed->eval(result);
|
||||||
|
@ -525,6 +555,11 @@ namespace NLGUI
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::string::size_type lastPos = targetNames[k].find_last_not_of(" ");
|
std::string::size_type lastPos = targetNames[k].find_last_not_of(" ");
|
||||||
|
if (startPos >= lastPos)
|
||||||
|
{
|
||||||
|
nlwarning("<splitLinkTargets> empty target encountered");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!splitLinkTarget(targetNames[k].substr(startPos, lastPos - startPos+1), parentGroup, ti.PropertyName, ti.Elem))
|
if (!splitLinkTarget(targetNames[k].substr(startPos, lastPos - startPos+1), parentGroup, ti.PropertyName, ti.Elem))
|
||||||
{
|
{
|
||||||
|
@ -539,6 +574,70 @@ namespace NLGUI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ***************************************************************************
|
||||||
|
bool CInterfaceLink::splitLinkTargetsExt(const std::string &targets, CInterfaceGroup *parentGroup,std::vector<CInterfaceLink::CTargetInfo> &targetsVect, std::vector<CInterfaceLink::CCDBTargetInfo> &cdbTargetsVect)
|
||||||
|
{
|
||||||
|
std::vector<std::string> targetNames;
|
||||||
|
NLMISC::splitString(targets, ",", targetNames);
|
||||||
|
targetsVect.clear();
|
||||||
|
targetsVect.reserve(targetNames.size());
|
||||||
|
cdbTargetsVect.clear(); // no reserve because less used
|
||||||
|
bool everythingOk = true;
|
||||||
|
for (uint k = 0; k < targetNames.size(); ++k)
|
||||||
|
{
|
||||||
|
std::string::size_type startPos = targetNames[k].find_first_not_of(" ");
|
||||||
|
if(startPos == std::string::npos)
|
||||||
|
{
|
||||||
|
// todo hulud interface syntax error
|
||||||
|
nlwarning("<splitLinkTargets> empty target encountered");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string::size_type lastPos = targetNames[k].find_last_not_of(" ");
|
||||||
|
if (startPos >= (lastPos+1))
|
||||||
|
{
|
||||||
|
nlwarning("<splitLinkTargets> empty target encountered");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetNames[k][startPos] == '@')
|
||||||
|
{
|
||||||
|
CInterfaceLink::CCDBTargetInfo ti;
|
||||||
|
ti.LeafName = targetNames[k].substr((startPos+1), (lastPos+1) - (startPos+1));
|
||||||
|
// Do not allow Write on SERVER: or LOCAL:
|
||||||
|
static const std::string dbServer= "SERVER:";
|
||||||
|
static const std::string dbLocal= "LOCAL:";
|
||||||
|
static const std::string dbLocalR2= "LOCAL:R2";
|
||||||
|
if( (0==ti.LeafName.compare(0, dbServer.size(), dbServer)) ||
|
||||||
|
(0==ti.LeafName.compare(0, dbLocal.size(), dbLocal))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (0!=ti.LeafName.compare(0, dbLocalR2.size(), dbLocalR2))
|
||||||
|
{
|
||||||
|
//nlwarning("You are not allowed to write on 'SERVER:...' or 'LOCAL:...' database");
|
||||||
|
nlstop;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ti.Leaf = NLGUI::CDBManager::getInstance()->getDbProp(ti.LeafName, false);
|
||||||
|
cdbTargetsVect.push_back(ti);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CInterfaceLink::CTargetInfo ti;
|
||||||
|
if (!splitLinkTarget(targetNames[k].substr(startPos, lastPos - startPos+1), parentGroup, ti.PropertyName, ti.Elem))
|
||||||
|
{
|
||||||
|
// todo hulud interface syntax error
|
||||||
|
nlwarning("<splitLinkTargets> Can't get link target");
|
||||||
|
everythingOk = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
targetsVect.push_back(ti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return everythingOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================
|
//===========================================================
|
||||||
void CInterfaceLink::checkNbRefs()
|
void CInterfaceLink::checkNbRefs()
|
||||||
{
|
{
|
||||||
|
|
|
@ -997,6 +997,7 @@ namespace NLGUI
|
||||||
|
|
||||||
|
|
||||||
std::vector<CInterfaceLink::CTargetInfo> targets;
|
std::vector<CInterfaceLink::CTargetInfo> targets;
|
||||||
|
std::vector<CInterfaceLink::CCDBTargetInfo> cdbTargets;
|
||||||
|
|
||||||
ptr = (char*) xmlGetProp (cur, (xmlChar*)"target");
|
ptr = (char*) xmlGetProp (cur, (xmlChar*)"target");
|
||||||
std::string target;
|
std::string target;
|
||||||
|
@ -1004,7 +1005,7 @@ namespace NLGUI
|
||||||
{
|
{
|
||||||
target = std::string( (const char*)ptr );
|
target = std::string( (const char*)ptr );
|
||||||
if( !editorMode )
|
if( !editorMode )
|
||||||
CInterfaceLink::splitLinkTargets(std::string((const char*)ptr), parentGroup, targets);
|
CInterfaceLink::splitLinkTargetsExt(std::string((const char*)ptr), parentGroup, targets, cdbTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional action handler
|
// optional action handler
|
||||||
|
@ -1022,7 +1023,7 @@ namespace NLGUI
|
||||||
if( !editorMode )
|
if( !editorMode )
|
||||||
{
|
{
|
||||||
CInterfaceLink *il = new CInterfaceLink;
|
CInterfaceLink *il = new CInterfaceLink;
|
||||||
il->init(targets, expr, action, params, cond, parentGroup); // init will add 'il' in the list of link present in 'elm'
|
il->init(targets, cdbTargets, expr, action, params, cond, parentGroup); // init will add 'il' in the list of link present in 'elm'
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -425,14 +425,15 @@ class CActionHandlerAddLink : public IActionHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CInterfaceLink::CTargetInfo> targetsVect;
|
std::vector<CInterfaceLink::CTargetInfo> targetsVect;
|
||||||
bool result = CInterfaceLink::splitLinkTargets(targets, parentGroup, targetsVect);
|
std::vector<CInterfaceLink::CCDBTargetInfo> cdbTargetsVect;
|
||||||
|
bool result = CInterfaceLink::splitLinkTargetsExt(targets, parentGroup, targetsVect, cdbTargetsVect);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
nlwarning("<CActionHandlerAddLink> Couldn't parse all links");
|
nlwarning("<CActionHandlerAddLink> Couldn't parse all links");
|
||||||
}
|
}
|
||||||
// add the link
|
// add the link
|
||||||
CInterfaceLink *il = new CInterfaceLink;
|
CInterfaceLink *il = new CInterfaceLink;
|
||||||
il->init(targetsVect, expr, ah, ahparam, ahcond, parentGroup);
|
il->init(targetsVect, cdbTargetsVect, expr, ah, ahparam, ahcond, parentGroup);
|
||||||
CInterfaceManager *im = CInterfaceManager::getInstance();
|
CInterfaceManager *im = CInterfaceManager::getInstance();
|
||||||
CWidgetManager::getInstance()->getParser()->addLink(il, id);
|
CWidgetManager::getInstance()->getParser()->addLink(il, id);
|
||||||
il->update();
|
il->update();
|
||||||
|
|
|
@ -558,7 +558,8 @@ void CPeopleInterraction::createTeamList()
|
||||||
{
|
{
|
||||||
CInterfaceLink *il = new CInterfaceLink;
|
CInterfaceLink *il = new CInterfaceLink;
|
||||||
vector<CInterfaceLink::CTargetInfo> targets;
|
vector<CInterfaceLink::CTargetInfo> targets;
|
||||||
il->init(targets, sExpr, sAction, sParams, sCond, TeamChat->getContainer());
|
vector<CInterfaceLink::CCDBTargetInfo> cdbTargets;
|
||||||
|
il->init(targets, cdbTargets, sExpr, sAction, sParams, sCond, TeamChat->getContainer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue